├── Changelog.txt ├── LICENSE ├── README.md ├── check-overlap.pl ├── ipv6gen.1 └── ipv6gen.pl /Changelog.txt: -------------------------------------------------------------------------------- 1 | 2 | 1.0 - fixed bug in the algorithm allocating bits from the middle when 3 | the delta was only 1 bit 4 | 0.9 - fixed bug centermost algorithm : 5 | at the very first round the bit following the center for the even 6 | number of bits was not picked 7 | - from Muggle L 8 | 0.8 - added checking of semantical correctness of input prefix 9 | (if there are non-zero bits after prefix length boundary, 10 | prefix is considered bad and ipv6gen exits with error.) 11 | 0.7 - added stepping between generated prefixes as input parameter 12 | 0.6 - fixed RFC 3513 non-compliancy bug (ipv6gen appended :: after 13 | prefixes longer than 112 bits) 14 | 0.5 - fixed zero padding bug - ipv6gen incorrectly generated prefixes 15 | not aligned to byte boundary. e.g. /64 prefixes were incorrectly 16 | generated from /49 prefixes) 17 | 0.4 - fixed bug when generating bits for middle allocation and 18 | delta with even number of bits 19 | 0.3 - check for format of IPv6 prefixes 20 | 0.2 - implemented allocation from the middle 21 | 0.1 - only allocation from the left/right is implemented 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ipv6gen 2 | IPv6 prefix generator 3 | 4 | ipv6gen is tool which generates list of IPv6 prefixes of given length from certain prefix 5 | according to [RFC 3531](http://www.ietf.org/rfc/rfc3531.txt). (A Flexible Method for Managing the Assignment of 6 | Bits of an IPv6 Address Block) 7 | 8 | This is intended as a helper script for either constructing IPv6 addressing scheme or allocating prefixes automatically. 9 | ipv6gen is structured into functions, which can be used in proprietary scripts. 10 | 11 | ipv6gen is written in Perl. 12 | 13 | ipv6gen is used in the following publications: 14 | *IPv6 Address Planning* by Tom Coffeen, published by O'Reilly in 2014. 15 | *IPv6 Fundamentals: A Straightforward Approach to Understanding IPv6, 2nd Edition* by Rick Graziani, published by Cisco Press in 2017. 16 | 17 | ipv6gen and other related scripts are GPL licensed. 18 | If you take some code out of ipv6gen and use it in your project, it would be nice if you mention that it comes from ipv6gen. 19 | 20 | How does it work ? 21 | - input : 22 | - prefix from which we will be generating smaller prefixes 23 | - method of bit allocation (left, right, from the middle) 24 | - size of prefixes to be generated 25 | - output : list of prefixes according to input data 26 | 27 | ## Changelog 28 | 29 | see `Changelog.txt` 30 | 31 | ## Examples ipv6gen 32 | 33 | ### Generating prefixes for subnets 34 | 35 | Say we want to generate /64 prefixes for application servers from 36 | 2001:1508:1003::/48, each /64 prefix for servers of given type. 37 | If method specifier is omited, allocation from the 38 | right will be used: 39 | 40 | ``` 41 | $ ./ipv6gen.pl 2001:1508:1003::/48 64 42 | 43 | 44 | 2001:1508:1003:0000::/64 45 | 2001:1508:1003:0001::/64 46 | 2001:1508:1003:0002::/64 47 | 2001:1508:1003:0003::/64 48 | 49 | ... 50 | 51 | 2001:1508:1003:FFFA::/64 52 | 2001:1508:1003:FFFB::/64 53 | 2001:1508:1003:FFFC::/64 54 | 2001:1508:1003:FFFD::/64 55 | 2001:1508:1003:FFFE::/64 56 | 2001:1508:1003:FFFF::/64 57 | ``` 58 | 59 | ### Splitting prefixes 60 | 61 | Or we just need to split /48 prefix into two prefixes: 62 | 63 | ``` 64 | $ ./ipv6gen.pl 2001:1508:1003::/48 49 65 | 2001:1508:1003:0000::/49 66 | 2001:1508:1003:8000::/49 67 | ``` 68 | 69 | This is actually example of allocation which is prone to errors. First byte 70 | after /48 boundary is 10000000 in binary which is 128 in decimal, which is 80 71 | in hexa. 72 | 73 | ### Flexible bit allocation 74 | 75 | Or we need to flexibly allocate prefixes which will be used for further 76 | allocations by starting allocating bits in the middle. In this example, 77 | debugging option `-d` will be used to see that the bits are really allocated 78 | this way: 79 | 80 | ``` 81 | $ ./ipv6gen.pl -d -m 2001:1508:1003::/48 53 82 | binary addr : 001000000000000100010101000010000001000000000011 83 | binary addr : 001000000000000100010101000010000001000000000011(48) 84 | delta 5 85 | zero filled : 00000 86 | converting 001000000000000100010101000010000001000000000011 # 00000 87 | 2001:1508:1003:0000::/53 88 | ----- round # 0 89 | left: 0 90 | central_bit: 3 91 | middle: 00100 92 | converting 001000000000000100010101000010000001000000000011 # 00100 93 | 2001:1508:1003:2000::/53 94 | ----- round # 1 95 | left: 1 96 | central_bit: 2 97 | middle: 01000 98 | converting 001000000000000100010101000010000001000000000011 # 01000 99 | 2001:1508:1003:4000::/53 100 | middle: 01100 101 | converting 001000000000000100010101000010000001000000000011 # 01100 102 | 2001:1508:1003:6000::/53 103 | ----- round # 2 104 | left: 0 105 | central_bit: 4 106 | middle: 00010 107 | converting 001000000000000100010101000010000001000000000011 # 00010 108 | 2001:1508:1003:1000::/53 109 | middle: 00110 110 | converting 001000000000000100010101000010000001000000000011 # 00110 111 | 2001:1508:1003:3000::/53 112 | middle: 01010 113 | converting 001000000000000100010101000010000001000000000011 # 01010 114 | 2001:1508:1003:5000::/53 115 | middle: 01110 116 | converting 001000000000000100010101000010000001000000000011 # 01110 117 | 2001:1508:1003:7000::/53 118 | 119 | ... 120 | ``` 121 | 122 | ### Leaving gaps between generated prefixes 123 | 124 | ipv6gen can also leave out gaps between each two generated prefixes. 125 | This is usefull when designing allocation schemes which should be 126 | extendable. Such scheme is for example using RIPE. Currently it gives out 127 | /32 prefixes to LIRs. For each LIR, it leaves out 7 subsequent prefixes, 128 | which will be used in case LIR will need more address space. These 129 | subsequent prefixes can be aggregated up to to /29 prefix. 130 | 131 | For example, one of the prefixes allocated by IANA to RIPE NCC is 132 | 2001:1400::/23 prefix. From this prefix, RIPE NCC further 133 | allocates /32 prefixes (in general) to LIRs. These prefixes are allocated 134 | using rightmost allocation. For each prefix, 7 subsequent prefixes are 135 | left out. So, RIPE could use ipv6gen for this task: 136 | 137 | ``` 138 | $ ./ipv6gen.pl -s 8 -r 2001:1400::/23 32 139 | 2001:1400::/32 140 | 2001:1408::/32 141 | 2001:1410::/32 142 | 2001:1418::/32 143 | 2001:1420::/32 144 | 2001:1428::/32 145 | 2001:1430::/32 146 | 2001:1438::/32 147 | 148 | ... 149 | ``` 150 | 151 | Compare this output with list of prefixes allocated by RIPE to LIRs to see that this is really the scheme 152 | RIPE uses. 153 | 154 | ### check-overlap 155 | 156 | This script checks if one prefix is allocated from second prefix. 157 | 158 | But check-overlap script does more than that. It does 3 kinds of checks: 159 | 160 | - IPv6 address format check 161 | It checks if IPv6 address format is correct (according to RFC3513, section 2.2.) 162 | XXX: implemented only in ipv6gen 163 | - correctness of IPv6 prefix address 164 | Checks for bits with value 1 beyond prefixlen boundary. 165 | This check is also implemented in ipv6gen. 166 | - check for overlapping prefixes 167 | Check if two prefixes overlap - i.e. second prefix was allocated from the first one. 168 | 169 | If one of the checks fails, following checks are not made: 170 | 171 | ``` 172 | $ ./check-overlap.pl 2001:1508:1000:FFFF::/45 2001:1508:1000:FF00:/56 173 | ---- doing prefix checks first 174 | --- checking 2001:1508:1000:FFFF::/45 175 | error in prefix : bit 1 found beyond prefixlen boundary 176 | binary representation of the prefix: 177 | 0010000000000001000101010000100000010000000000001111111111111111 178 | 001000000000000100010101000010000001000000000 0001111111111111111 179 | /45 ^ 180 | --- checking 2001:1508:1000:FF00:/56 ... OK 181 | ``` 182 | 183 | For some prefixes it is not visible on the first sight, if they are overlapping: 184 | 185 | ``` 186 | $ ./check-overlap.pl 2001:1508:FFD0:40::/50 2001:1508:FFB0:C0::/51 187 | ---- doing prefix checks first 188 | --- checking 2001:1508:FFD0:40::/50 ... OK 189 | --- checking 2001:1508:FFB0:C0::/51 ... OK 190 | --- checking overlap ... prefixes do NOT overlap 191 | 00100000000000010001010100001000111111111101000001 000000 192 | 00100000000000010001010100001000111111111011000011 000000 193 | /50 194 | ``` 195 | 196 | ... but these are not. 197 | 198 | These are clear: 199 | 200 | ``` 201 | $ ./check-overlap.pl 2001:1508::/32 2001:1508:FFB0:C0::/52 202 | ---- doing prefix checks first 203 | --- checking 2001:1508::/32 ... OK 204 | --- checking 2001:1508:FFB0:C0::/52 ... OK 205 | --- checking overlap ... OK (overlapping) 206 | ``` 207 | 208 | ## Known bugs/TODO 209 | 210 | see https://github.com/vladak/ipv6gen/issues 211 | -------------------------------------------------------------------------------- /check-overlap.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # check if two IPv6 prefixes overlap correctly 4 | # 5 | # functions for conversions betweeen hex and binary are 6 | # based on script hex2bin.pl by Stas Bekman 7 | # 8 | # Vladimir Kotal , 2005 9 | # 10 | 11 | use Getopt::Std; 12 | use strict; 13 | 14 | $0 =~ s|^.*/||; # cut the basename of the command 15 | 16 | # opt vars 17 | my $quiet = 0; 18 | my $debug = 0; 19 | 20 | # global variables 21 | my $error = 0; 22 | 23 | # Define the separation character between each binary number 24 | my $char = " "; 25 | 26 | # print help and exit 27 | sub help () { 28 | print "usage: $0 \n"; 29 | exit(1); 30 | } 31 | 32 | sub debug () { 33 | print @_ if ($debug > 0); 34 | 35 | } 36 | 37 | # convert one char in hex to binary 38 | sub hex2bin_c { 39 | my ($digit) = shift; 40 | return unpack("B4", pack("H", $digit)); 41 | } 42 | 43 | 44 | # convert string with hex representation to binary 45 | sub hex2bin { 46 | my $in = shift; 47 | my $out; 48 | 49 | my @digits = split //, $in; 50 | for (@digits) { 51 | $out = $out . hex2bin_c($_); 52 | } 53 | return $out; 54 | } 55 | 56 | 57 | # XXX 58 | sub addr2bin { 59 | my $prefix = shift; 60 | my @sects = split(/:/, $prefix); 61 | my $s; 62 | my $tmp; 63 | my $addr_bin = ""; 64 | 65 | for $s (@sects) { 66 | $tmp = &hex2bin($s); 67 | $addr_bin = $addr_bin . $tmp; 68 | } 69 | return $addr_bin; 70 | } 71 | 72 | 73 | # 74 | # print binary representation of prefix split to 2 sections 75 | # 76 | # arg1: binary representation of prefix 77 | # arg2: length 78 | # 79 | sub print_split { 80 | my $bits = shift; 81 | my $len= shift; 82 | 83 | &debug("$bits\n"); 84 | print substr($bits, 0, $len) 85 | . " " 86 | . substr($bits, $len) 87 | . "\n"; 88 | } 89 | 90 | # XXX 91 | sub print_boundary_mark () { 92 | my $idx = shift; 93 | my $len = shift; 94 | 95 | my $i; 96 | 97 | for ($i = 0; $i < $len - 3; $i++) { 98 | print " "; 99 | } 100 | print "\/$len"; 101 | if ($idx > 0) { 102 | for ($i = 0; $i < $idx + 1; $i++) { 103 | print " "; 104 | } 105 | print "^"; 106 | } 107 | print "\n"; 108 | } 109 | 110 | # 111 | # check for 1 bits behind prefix length limit 112 | # 113 | # arg1: binary representation of address 114 | # arg2: length of prefix 115 | # 116 | sub check_pfx_bin () { 117 | my $bits = shift; 118 | my $len = shift; 119 | my $idx; 120 | 121 | my $beyond_pfxlen = substr($bits, $len); 122 | if ($beyond_pfxlen =~ /1/) { 123 | if ($quiet != 1) { 124 | print "\nerror in prefix : bit 1 found beyond prefixlen boundary\n"; 125 | print "binary representation of the prefix:\n"; 126 | &print_split($bits, $len); 127 | 128 | $idx = index($beyond_pfxlen, "1"); 129 | &print_boundary_mark($idx, $len); 130 | } 131 | $error++; 132 | return(1); 133 | } 134 | } 135 | 136 | 137 | # 138 | # check if smaller prefix fits into bigger prefix 139 | # 140 | # arg1: bigger IPv6 prefix 141 | # arg2: smaller IPv6 prefix 142 | # 143 | sub check_overlap { 144 | my $prefix1 = shift; 145 | my $prefix2 = shift; 146 | 147 | my $big_pfx_part; 148 | my $big_pfx_len; 149 | my $small_pfx_part; 150 | my $small_pfx_len; 151 | 152 | ($big_pfx_part, $big_pfx_len) = split(/\//, $prefix1); 153 | ($small_pfx_part, $small_pfx_len) = split(/\//, $prefix2); 154 | 155 | my $big_bits = &addr2bin($big_pfx_part); 156 | my $small_bits = &addr2bin($small_pfx_part); 157 | 158 | # smaller prefixlen makes bigger prefix 159 | if ($big_pfx_len > $small_pfx_len) { 160 | print "bigger prefix should be specified first\n"; 161 | return(1); 162 | } 163 | 164 | print "--- checking overlap" if ($quiet == 0); 165 | 166 | my $f = substr($big_bits, 0, $big_pfx_len); 167 | my $s = substr($small_bits, 0, $big_pfx_len); 168 | if ($f cmp $s) { 169 | print " ... prefixes do NOT overlap\n" if ($quiet == 0); 170 | # print "$f\n$s\n"; 171 | &debug("$prefix1\n"); 172 | &print_split($big_bits, $big_pfx_len); 173 | &debug("$prefix2\n"); 174 | &print_split($small_bits, $big_pfx_len); 175 | &print_boundary_mark(0, $big_pfx_len); 176 | $error++; 177 | return(1); 178 | } 179 | print " ... OK (overlapping)\n" if ($quiet == 0); 180 | } 181 | 182 | 183 | # 184 | # check prefix 185 | # this is really just a wrapper to check_pfx_bin() 186 | # 187 | # arg1: prefix 188 | # 189 | sub check_pfx () { 190 | my $prefix = shift; 191 | my $pfx_part; 192 | my $pfx_len; 193 | 194 | ($pfx_part, $pfx_len) = split(/\//, $prefix); 195 | 196 | my $pfx_bits = &addr2bin($pfx_part); 197 | 198 | print "--- checking $prefix" if ($quiet == 0); 199 | if (!&check_pfx_bin($pfx_bits, $pfx_len)) { 200 | print " ... OK\n" if ($quiet == 0); 201 | } 202 | } 203 | 204 | 205 | # 206 | # check format of prefix 207 | # arg1: prefix 208 | # XXX 209 | # 210 | sub check_fmt() { 211 | my $prefix = shift; 212 | 213 | return(0); 214 | } 215 | 216 | # 217 | # MAIN 218 | # 219 | my $opts = {}; 220 | &getopts('qdh', $opts); 221 | &help if exists $opts->{"h"}; 222 | $debug = 1 if exists $opts->{"d"}; 223 | $quiet = 1 if exists $opts->{"q"}; 224 | 225 | &help if (scalar(@ARGV) != 2); 226 | 227 | 228 | # check IPv6 prefix format 229 | # XXX check if IPv6 address has the right format 230 | if (&check_fmt($ARGV[0]) || &check_fmt($ARGV[1])) { 231 | print "bad prefix format\n"; 232 | exit(1); 233 | } 234 | 235 | # run the checks 236 | print "---- doing prefix checks first\n" if ($quiet == 0); 237 | &check_pfx($ARGV[0]); 238 | &check_pfx($ARGV[1]); 239 | 240 | &check_overlap($ARGV[0], $ARGV[1]) if ($error == 0); 241 | 242 | exit (1) if ($error); 243 | -------------------------------------------------------------------------------- /ipv6gen.1: -------------------------------------------------------------------------------- 1 | .TH ipv6gen 1 2 | .SH NAME 3 | ipv6gen \- IPv6 prefix generator. 4 | .SH SYNOPSIS 5 | .B ipv6gen 6 | [ 7 | .B \-d 8 | ] 9 | [ 10 | .B \-lmr 11 | ] 12 | [ 13 | .B \-s 14 | ] 15 | .B 16 | 17 | .SH DESCRIPTION 18 | .PP 19 | \fBipv6gen\fP is tool which generates list of IPv6 prefixes of given 20 | prefix length from certain prefix according to RFC 3531. 21 | .PP 22 | .SH OPTIONS 23 | .TP 24 | .B \-d 25 | debug mode. Displays allocated prefix as bit array. 26 | .TP 27 | .B \-l 28 | allocate bits from the left. e.g. for delta 4, the bit array looks like this: 29 | 30 | .nf 31 | 0000 32 | 1000 33 | 0100 34 | 1100 35 | 0010 36 | 1010 37 | 0110 38 | 1110 39 | 0001 40 | 1001 41 | 0101 42 | 1101 43 | 0011 44 | 1011 45 | 0111 46 | 1111 47 | .fi 48 | .Ed 49 | .TP 50 | .B \-r 51 | allocate bits from the right. This is the same as allocation from the left 52 | but reversed. e.g. again for delta of value 4: 53 | 54 | .nf 55 | 0000 56 | 0001 57 | 0010 58 | 0011 59 | 0100 60 | 0101 61 | 0110 62 | 0111 63 | 1000 64 | 1001 65 | 1010 66 | 1011 67 | 1100 68 | 1101 69 | 1110 70 | 1111 71 | .fi 72 | .TP 73 | .B \-m 74 | allocate bits from the middle. This method tries to allocate bits close 75 | to the axis of delta first and then proceeds to sides. 76 | For delta of value 4 it is: 77 | 78 | .nf 79 | 0000 80 | 0100 81 | 0010 82 | 0110 83 | 1000 84 | 1100 85 | 1010 86 | 1110 87 | 0001 88 | 0011 89 | 0101 90 | 0111 91 | 1001 92 | 1011 93 | 1101 94 | 1111 95 | .fi 96 | 97 | For delta of value 5, it is: 98 | 99 | .nf 100 | 00000 101 | 00100 102 | 01000 103 | 01100 104 | 00010 105 | 00110 106 | 01010 107 | 01110 108 | \&... 109 | 110 | 00001 111 | 00011 112 | 00101 113 | 00111 114 | 01001 115 | 01011 116 | 01101 117 | 01111 118 | 10001 119 | 10011 120 | 10101 121 | 10111 122 | 11001 123 | 11011 124 | 11101 125 | 11111 126 | .fi 127 | .TP 128 | .B \-s 129 | set step between generated prefixes. It will leave out step-1 prefixes 130 | between each two generated prefixes. default step value is 1. 131 | .TP 132 | .B \-n 133 | maximum amount of prefixes to generate - only applicable in left and right modes. 134 | .SH EXAMPLES 135 | If we need to to split /48 prefix into two prefixes: 136 | 137 | .nf 138 | worm[~/IPv6/ipv6gen]> ./ipv6gen.pl 2001:1508:1003::/48 49 139 | 2001:1508:1003:0000::/49 140 | 2001:1508:1003:8000::/49 141 | .fi 142 | 143 | To allocate bits from the middle from /32 prefix with 4-bits wide delta: 144 | 145 | .nf 146 | worm[~/IPv6/ipv6gen]> ./ipv6gen.pl -m 2001:1508::/32 36 147 | 2001:1508:0000::/36 148 | 2001:1508:4000::/36 149 | 2001:1508:2000::/36 150 | 2001:1508:6000::/36 151 | 2001:1508:8000::/36 152 | 2001:1508:C000::/36 153 | 2001:1508:A000::/36 154 | 2001:1508:E000::/36 155 | 2001:1508:1000::/36 156 | 2001:1508:3000::/36 157 | 2001:1508:5000::/36 158 | 2001:1508:7000::/36 159 | 2001:1508:9000::/36 160 | 2001:1508:B000::/36 161 | 2001:1508:D000::/36 162 | 2001:1508:F000::/36 163 | .fi 164 | .SH AUTHOR 165 | Vladimir Kotal 166 | .SH WEBPAGE 167 | http://techie.devnull.cz/ipv6/ipv6gen 168 | .SH BUGS/TODO 169 | ipv6gen should be converted to Perl library/module. 170 | -------------------------------------------------------------------------------- /ipv6gen.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # IPv6 prefix generator 4 | # - generates list of prefixes of certain size from given prefix 5 | # with one of 3 methods for bit allocation (according to 6 | # RFC3531) 7 | # 8 | # 9 | # Vladimir Kotal , 2005 10 | # 11 | 12 | use Getopt::Std; 13 | use POSIX qw(ceil floor); 14 | use strict; 15 | 16 | $0 =~ s|^.*/||; # cut the basename of the command 17 | 18 | $|=1; 19 | 20 | # variables 21 | my $debug = 0; # 1 - print debug messages 22 | my $method = "r"; # strategy for generating prefixes, default : right 23 | my $method_set = 0; # indicate if strategy was set 24 | my $step = 1; # default step between generated prefixes 25 | my $userlimit = 0; # default user defined generation limit, 0 = no limit 26 | my $version = "1.0"; 27 | 28 | # 29 | # print help and exit 30 | # 31 | sub help () 32 | { 33 | print "$0 (v$version) - generates IPv6 prefixes from given \n"; 34 | print " IPv6 prefix pool using given strategy\n\n"; 35 | print "usage: ipv6gen [switch|strategy] \n"; 36 | print "\nstrategies:\n"; 37 | print "-l\t\tleft to right\n"; 38 | print "-r\t\tright to left\n"; 39 | print "-m\t\tfrom the middle out\n"; 40 | print "\nswitches:\n"; 41 | print "-d\t\tdisplay debug messages\n"; 42 | print "-s \t\tstep between prefixes\n"; 43 | print "-n \t\tlimit (only in left/rigth modes)\n"; 44 | print "\n"; 45 | 46 | exit(1); 47 | } 48 | 49 | sub debug () { 50 | print @_ if ($debug > 0); 51 | 52 | } 53 | 54 | # 55 | # pad string from left with zeroes 56 | # 57 | # arg1: string to be padded 58 | # arg2: length of resulting string 59 | # arg3: 1 - pad from left, 0 - pad from right 60 | # 61 | sub zero_pad () { 62 | my $str = shift; 63 | my $len = shift; 64 | my $left = shift; 65 | 66 | my $i; 67 | 68 | my $strlen = length($str); 69 | for ($i = 0; $i < $len - $strlen; $i++) { 70 | if ($left) { 71 | $str = "0" . $str; 72 | } else { 73 | $str = $str . "0"; 74 | } 75 | } 76 | return $str; 77 | } 78 | 79 | # convert dec to bin 80 | # and output binary number w/out leading zeroes 81 | sub dec2bin_old() { 82 | my $arg = shift @_; 83 | my $str = unpack('B32', pack('C', $arg)) . ""; 84 | 85 | # strip leading zeroes 86 | if ($str !~ /00000000/) { 87 | $str =~ s/^0+// 88 | } else { 89 | $str = "0"; 90 | } 91 | return $str; 92 | } 93 | 94 | sub dec2bin { 95 | my $str = unpack("B32", pack("N", shift)); 96 | $str =~ s/^0+(?=\d)//; # otherwise you'll get leading zeros 97 | return $str; 98 | } 99 | 100 | # convert one char in hex to binary 101 | sub hex2bin_c { 102 | my ($digit) = shift; 103 | return unpack("B4", pack("H", $digit)); 104 | } 105 | 106 | # convert string with hex representation to binary 107 | sub hex2bin { 108 | my $in = shift; 109 | my $out; 110 | 111 | my @digits = split //, $in; 112 | for (@digits) { 113 | $out = $out . hex2bin_c($_); 114 | } 115 | return $out; 116 | } 117 | 118 | # convert one char from binary to hex 119 | # input char must be 4 bits long 120 | sub bin2hex_c { 121 | my $binary = shift; 122 | 123 | my $str = unpack("H", pack("B4", $binary)); 124 | $str =~ tr/a-f/A-F/; 125 | return $str; 126 | } 127 | 128 | # convert binary representation of IPv6 address to colon format 129 | # 130 | # arg1: binary represenatation of IPv6 addr 131 | # 132 | # NOTE: this function does not output valid IPv6 address 133 | # 134 | sub binaddr_to_dots { 135 | my $bin = shift; 136 | 137 | my $out = ""; 138 | my $first = 1; 139 | my $converted = 0; # number of bits converted 140 | my $cbd = 0; # number of chars beyond : 141 | 142 | my $conv; 143 | my $lastconv; 144 | # &debug("bin : $bin\n"); 145 | 146 | while (length($bin) > 0) { 147 | $conv = substr($bin, 0, 4); 148 | # print "conv : $conv\n"; 149 | $lastconv = bin2hex_c($conv); 150 | $out = $out . $lastconv; 151 | $converted += length($conv); 152 | $cbd++; 153 | if ((!$first) && !($converted % 16) && (length($bin) != 4)) { 154 | # $binlen = length($bin); 155 | # &debug("adding ':' [$binlen]\n"); 156 | $out = $out . ":"; 157 | $cbd = 0; 158 | } 159 | $first = 0; 160 | $bin = substr($bin, 4, length($bin) - 4); 161 | } 162 | # print "converted = $converted\n"; 163 | # pad with null till next : boundary 164 | if ($cbd > 0) { 165 | $out = $out . substr("0000", 0, 4 - $cbd); 166 | } 167 | return $out; 168 | } 169 | 170 | # 171 | # convert IPv6 address to binary 172 | # XXX prefixlen ? 173 | # 174 | # arg1: XXX 175 | # 176 | sub addr2bin { 177 | my $prefix = shift; 178 | 179 | my @sects = split(/:/, $prefix); 180 | my $s; 181 | my $tmp; 182 | my $addr_bin; 183 | 184 | for $s (@sects) { 185 | # pad to zeroes from the left according to RFC 3513, section 2.3 186 | # (Internet Protocol Version 6 (IPv6) Addressing Architecture) 187 | $s = &zero_pad($s, 4, 1); 188 | $tmp = &hex2bin($s); 189 | $addr_bin = $addr_bin . $tmp; 190 | } 191 | return $addr_bin; 192 | } 193 | 194 | # 195 | # check prefix format and print it if it passes the check 196 | # 197 | # arg1: IPv6 prefix (with prefixlen) 198 | # 199 | sub print_pfx () { 200 | my $pfx = shift; 201 | 202 | if (&ipv6pfx_check($pfx)) { 203 | print "$pfx\n"; 204 | } else { 205 | print "bad prefix format: $pfx\n"; 206 | print "#### please report this bug\n"; 207 | exit(1); 208 | } 209 | } 210 | 211 | # 212 | # check if IPv6 address is valid 213 | # 214 | # idea and parts of the regexp by Glynn Beeken via regexlib.com 215 | # 216 | # arg1: prefix (in format addr/prefixlen) 217 | # return: -1 on error, 1 otherwise 218 | # 219 | sub ipv6pfx_check () { 220 | my $prefix = shift; 221 | 222 | my $addr; 223 | my $pfx_len; 224 | 225 | ($addr, $pfx_len) = split(/\//, $prefix); 226 | &debug("checking $prefix = $addr / $pfx_len\n"); 227 | return (-1) if ($pfx_len > 128); 228 | 229 | return (1) if ($addr =~ /([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}/); 230 | return (1) if ($addr =~ /[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){5}::[0-9A-Fa-f]{1,4}/); 231 | return (1) if ($addr =~ /[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){4}::[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,1}/); 232 | return (1) if ($addr =~ /[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){3}::[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,2}/); 233 | return (1) if ($addr =~ /[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){2}::[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,3}/); 234 | return (1) if ($addr =~ /[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}::[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,4})/); 235 | return (1) if ($addr =~ /[0-9A-Fa-f]{1,4}::[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5}/); 236 | return (1) if ($addr =~ /[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,6}::/); 237 | return (1) if ($addr =~ /::[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,6}/); 238 | return (1) if ($addr =~ /::/); 239 | 240 | return(-1); 241 | } 242 | 243 | # 244 | # print binary representation of prefix split to 2 sections 245 | # 246 | # arg1: binary representation of prefix 247 | # arg2: length 248 | # NOTE: taken from check-overlap.pl 249 | # 250 | sub print_split { 251 | my $bits = shift; 252 | my $len= shift; 253 | 254 | &debug("$bits\n"); 255 | print substr($bits, 0, $len) 256 | . " " 257 | . substr($bits, $len) 258 | . "\n"; 259 | } 260 | 261 | # 262 | # print boundary mark 263 | # arg1: index 264 | # arg2: length 265 | # NOTE: taken from check-overlap.pl 266 | # 267 | sub print_boundary_mark () { 268 | my $idx = shift; 269 | my $len = shift; 270 | 271 | my $i; 272 | 273 | for ($i = 0; $i < $len - 3; $i++) { 274 | print " "; 275 | } 276 | print "\/$len"; 277 | if ($idx > 0) { 278 | for ($i = 0; $i < $idx + 1; $i++) { 279 | print " "; 280 | } 281 | print "^"; 282 | } 283 | print "\n"; 284 | } 285 | 286 | # 287 | # check for 1 bits behind prefix length limit 288 | # 289 | # arg1: binary representation of address 290 | # arg2: length of prefix 291 | # NOTE: taken from check-overlap.pl 292 | # 293 | sub check_pfx_bin () { 294 | my $bits = shift; 295 | my $len = shift; 296 | my $idx; 297 | 298 | my $beyond_pfxlen = substr($bits, $len); 299 | if ($beyond_pfxlen =~ /1/) { 300 | print("\nerror in prefix : bit 1 found beyond prefixlen boundary\n"); 301 | print("binary representation of the prefix:\n"); 302 | &print_split($bits, $len); 303 | 304 | $idx = index($beyond_pfxlen, "1"); 305 | &print_boundary_mark($idx, $len); 306 | exit(1); 307 | } 308 | } 309 | 310 | 311 | # convert binary representation of prefix and print it on STDOUT 312 | sub print_binpfx () { 313 | my $pfx = shift; 314 | my $append = shift; 315 | my $glen = shift; 316 | 317 | &debug("converting $pfx $append\n"); 318 | my $addr = &binaddr_to_dots($pfx . $append); 319 | # do not append :: to prefixes with length bigger than 112 320 | # in order to be compliant with RFC 3513, section 2.2 321 | # NOTE: this would have to be changed with support of compressed format 322 | if ($glen <= 112) { 323 | $addr = $addr . "::"; 324 | } 325 | 326 | # To comply with RFC 5952 (https://tools.ietf.org/html/rfc5952) this should output lower case characters 327 | $addr = lc $addr; 328 | 329 | &print_pfx("$addr/$glen"); 330 | } 331 | 332 | # 333 | # generate list of prefixes by allocating bits from the middle 334 | # NOTE: this function actually prints prefixes to STDOUT 335 | # 336 | # arg1: binary representation of prefix pool addr 337 | # arg2: length of prefix pool 338 | # arg3: length of prefixes to be generared from pool 339 | # 340 | sub generate_m () { 341 | my $addr_bin_strip = shift; 342 | my $plen = shift; 343 | my $glen = shift; 344 | 345 | my $i; 346 | my $rnd; 347 | my $str; 348 | my $addr; 349 | 350 | my $left = 0; 351 | 352 | my $delta = $glen - $plen; 353 | &debug("delta $delta\n"); 354 | # number of rounds is equal to number of bits to be filled 355 | my $limit = $delta; 356 | my $rnd_limit = 0; 357 | 358 | # position of first bit with value 1 359 | my $central_bit = ceil($delta / 2); 360 | 361 | # zero-filled str is speciall case 362 | $str = &zero_pad($str, $delta, 1); 363 | &debug("zero filled : $str\n"); 364 | &print_binpfx($addr_bin_strip, $str, $glen); 365 | 366 | if (($delta % 2) == 0) { 367 | $left = 1; 368 | # Even number of bits, pick the bit following the center 369 | # RFC3531 Section 3.3 370 | # muggle19355@gmail.com 371 | $central_bit++; 372 | } 373 | 374 | for ($rnd = 0; $rnd < $limit; $rnd++) { 375 | $rnd_limit=2 ** $rnd; # number of passes in each round 376 | 377 | # special case for even number of bits at the very first round 378 | if ($rnd_limit == 1) 379 | { 380 | if ($left == 1 && ($delta % 2) == 0) 381 | { 382 | $left=0; 383 | } 384 | } 385 | 386 | &debug("----- round \# $rnd\n"); 387 | &debug("left: $left\n"); 388 | &debug("central_bit: $central_bit\n"); 389 | for ($i = 0; $i < $rnd_limit; $i++) { 390 | $str = &dec2bin($i); 391 | #&debug("dec2bin: $i = $str\n"); 392 | 393 | my $tmp = ""; 394 | # $str = &zero_pad($str, $central_bit, 1); 395 | if ($left == 1) { 396 | $tmp = &zero_pad($tmp, $central_bit - 1, 1); 397 | $tmp = $tmp . "1"; 398 | # &debug("tmp: $tmp\n"); 399 | $str = reverse $str; 400 | $str = $tmp . $str; 401 | } else { 402 | # This will take care of the delta == 1 case 403 | if ($i == 0) { 404 | $str = "1"; 405 | } else { 406 | $str = $str . "1"; 407 | } 408 | $str = &zero_pad($str, $central_bit, 1); 409 | } 410 | $str = &zero_pad($str, $delta, 0); 411 | &debug("middle: $str\n"); 412 | &print_binpfx($addr_bin_strip, $str, $glen); 413 | } 414 | $left = ($left + 1) % 2; 415 | if ($left) { 416 | $central_bit = $central_bit - $rnd -1; 417 | } else { 418 | $central_bit = $central_bit + $rnd +1; 419 | } 420 | } 421 | } 422 | 423 | # 424 | # generate list of prefixes by allocating bits from the left/right 425 | # NOTE: this function actually prints prefixes to STDOUT 426 | # 427 | # arg1: binary representation of prefix pool addr 428 | # arg2: length of prefix pool 429 | # arg3: length of prefixes to be generared from pool 430 | # arg4: 1 - generate from left, 0 - right 431 | # 432 | sub generate_rl () { 433 | my $addr_bin_strip = shift; 434 | my $plen = shift; 435 | my $glen = shift; 436 | my $reverse = shift; 437 | 438 | my $i; 439 | my $str; 440 | my $addr; 441 | 442 | my $delta = $glen - $plen; 443 | &debug("delta $delta\n"); 444 | my $limit = 2 ** $delta; 445 | die "step bigger than limit ($step > $limit)" if ($step > $limit); 446 | 447 | if ($userlimit > 0 && $userlimit < $limit) { 448 | $limit = $userlimit; 449 | } 450 | 451 | &debug("will generate " . $limit/$step . " prefixes\n"); 452 | for ($i = 0; $i < $limit; $i+=$step) { 453 | $str = &dec2bin($i); 454 | # my $debug_str = reverse $str if ($reverse); 455 | # &debug("generated bits: $debug_str\n"); 456 | $str = &zero_pad($str, $delta, 1); 457 | $str = reverse $str if ($reverse); 458 | 459 | &print_binpfx($addr_bin_strip, $str, $glen); 460 | } 461 | } 462 | 463 | # 464 | # generate IPv6 prefixes from IPv6 prefix pool using given strategy 465 | # arg1: prefix to generate from 466 | # arg2: length of prefixes to be generated 467 | # arg3: method for 468 | # 469 | sub generate () { 470 | my $prefix = shift; # prefix pool 471 | my $plen = shift; # length of prefix pool 472 | my $glen = shift; # length of prefixes to be generated 473 | my $method = shift; 474 | 475 | my $addr_bin = &addr2bin($prefix); 476 | &check_pfx_bin($addr_bin, $plen); 477 | 478 | &debug("binary addr : $addr_bin (not padded/cropped)\n"); 479 | # pad the prefix to $plen, otherwise we would get wrong results 480 | $addr_bin = &zero_pad($addr_bin, $plen, 0); 481 | my $addr_bin_strip = substr($addr_bin, 0, $plen); 482 | &debug("binary addr : " . $addr_bin_strip . "($plen) \n"); 483 | 484 | # call proper generating function 485 | if ($method =~ /r/) { 486 | &generate_rl($addr_bin_strip, $plen, $glen, 0); 487 | } elsif ($method =~ /l/) { 488 | &generate_rl($addr_bin_strip, $plen, $glen, 1); 489 | } elsif ($method =~ /m/) { 490 | &generate_m($addr_bin_strip, $plen, $glen); 491 | } 492 | } 493 | 494 | # 495 | # set strategy for generating prefixes 496 | # 497 | sub set_method () { 498 | $method = shift @_; 499 | 500 | die "only single step is possible for middle bit allocation" 501 | if (($step > 1) and ($method =~ /^m$/)); 502 | &debug("setting method $method\n"); 503 | 504 | &help if ($method_set == 1); 505 | } 506 | 507 | # -------------------------------------------------------------------------- 508 | # MAIN 509 | # -------------------------------------------------------------------------- 510 | 511 | my $opts = {}; 512 | &getopts('s:n:dhmlr', $opts); 513 | &help if exists $opts->{"h"}; 514 | $debug = 1 if exists $opts->{"d"}; 515 | $step = $opts->{"s"} if exists $opts->{"s"}; 516 | $userlimit = $opts->{"n"} if exists $opts->{"n"}; 517 | 518 | &help if (scalar(@ARGV) != 2); 519 | 520 | &set_method("l") if exists $opts->{"l"}; 521 | &set_method("r") if exists $opts->{"r"}; 522 | &set_method("m") if exists $opts->{"m"}; 523 | 524 | if (&ipv6pfx_check($ARGV[0]) < 0) { 525 | print "bad prefix $ARGV[0]\n"; 526 | exit(1); 527 | } 528 | 529 | my $addr; 530 | my $pfx_len; 531 | 532 | ($addr, $pfx_len) = split(/\//, $ARGV[0]); 533 | 534 | my $genlen = $ARGV[1]; 535 | if ($genlen !~ /^[0-9]+$/) { 536 | print "length of prefix to be generated is not number: $genlen\n"; 537 | exit(1); 538 | } 539 | 540 | if ($genlen < $pfx_len) { 541 | print "cannot generate \/$genlen prefixes from \/$pfx_len prefix\n"; 542 | exit(1); 543 | } 544 | 545 | if ($genlen > 128) { 546 | print "invalid prefix length: \/$genlen\n"; 547 | exit(1); 548 | } 549 | 550 | &generate($addr, $pfx_len, $genlen, $method); 551 | 552 | # EOF 553 | --------------------------------------------------------------------------------