|  | 
|  | 1 | +#!/usr/local/bin/php | 
|  | 2 | +<?php | 
|  | 3 | + | 
|  | 4 | +/* | 
|  | 5 | + * Copyright (C) 2025 Deciso B.V. | 
|  | 6 | + * Copyright (C) 2022-2024 Franco Fichtner <[email protected]> | 
|  | 7 | + * Copyright (C) 2012 Seth Mos <[email protected]> | 
|  | 8 | + * All rights reserved. | 
|  | 9 | + * | 
|  | 10 | + * Redistribution and use in source and binary forms, with or without | 
|  | 11 | + * modification, are permitted provided that the following conditions are met: | 
|  | 12 | + * | 
|  | 13 | + * 1. Redistributions of source code must retain the above copyright notice, | 
|  | 14 | + *    this list of conditions and the following disclaimer. | 
|  | 15 | + * | 
|  | 16 | + * 2. Redistributions in binary form must reproduce the above copyright | 
|  | 17 | + *    notice, this list of conditions and the following disclaimer in the | 
|  | 18 | + *    documentation and/or other materials provided with the distribution. | 
|  | 19 | + * | 
|  | 20 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | 
|  | 21 | + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | 
|  | 22 | + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 
|  | 23 | + * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, | 
|  | 24 | + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 
|  | 25 | + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 
|  | 26 | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 
|  | 27 | + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 
|  | 28 | + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 
|  | 29 | + * POSSIBILITY OF SUCH DAMAGE. | 
|  | 30 | + */ | 
|  | 31 | + | 
|  | 32 | +require_once 'config.inc'; | 
|  | 33 | +require_once 'interfaces.inc'; | 
|  | 34 | +require_once 'util.inc'; | 
|  | 35 | + | 
|  | 36 | +$leases_file = '/var/db/kea/kea-leases6.csv'; | 
|  | 37 | +if (!file_exists($leases_file)) { | 
|  | 38 | +    exit(1); | 
|  | 39 | +} | 
|  | 40 | + | 
|  | 41 | +$duid_arr = []; | 
|  | 42 | +$now = time(); | 
|  | 43 | +if (($fh = fopen($leases_file, 'r')) !== false) { | 
|  | 44 | +    $header = fgetcsv($fh); | 
|  | 45 | + | 
|  | 46 | +    while (($row = fgetcsv($fh)) !== false) { | 
|  | 47 | +        $lease = @array_combine($header, $row); | 
|  | 48 | +        if (empty($lease['duid']) || empty($lease['lease_type']) || empty($lease['address'])) { | 
|  | 49 | +            continue; | 
|  | 50 | +        } | 
|  | 51 | + | 
|  | 52 | +        $type = trim($lease['lease_type']); | 
|  | 53 | +        $prefix_len = (int)$lease['prefix_len']; | 
|  | 54 | +        $expire = (int)$lease['expire']; | 
|  | 55 | +        $duid = strtolower(trim($lease['duid'])); | 
|  | 56 | +        $address = trim($lease['address']); | 
|  | 57 | + | 
|  | 58 | +        /* Skip expired leases */ | 
|  | 59 | +        if ($expire <= $now) { | 
|  | 60 | +            continue; | 
|  | 61 | +        } | 
|  | 62 | + | 
|  | 63 | +        if (!isset($duid_arr[$duid])) { | 
|  | 64 | +            $duid_arr[$duid] = []; | 
|  | 65 | +        } | 
|  | 66 | + | 
|  | 67 | +        /* IA_NA: type 0, prefix_len 128 - used as gateway */ | 
|  | 68 | +        if ($type === '0' && $prefix_len === 128) { | 
|  | 69 | +            $duid_arr[$duid]['address'] = $address; | 
|  | 70 | +        } | 
|  | 71 | +        /* IA_PD: type 2, prefix_len <= 64 - the delegated prefix */ | 
|  | 72 | +        elseif ($type === '2' && $prefix_len <= 64) { | 
|  | 73 | +            $prefix = "{$address}/{$prefix_len}"; | 
|  | 74 | +            $duid_arr[$duid]['prefix'][] = $prefix; | 
|  | 75 | +        } | 
|  | 76 | +    } | 
|  | 77 | +    fclose($fh); | 
|  | 78 | +} | 
|  | 79 | + | 
|  | 80 | +$routes = []; | 
|  | 81 | + | 
|  | 82 | +/* collect active leases */ | 
|  | 83 | +foreach ($duid_arr as $entry) { | 
|  | 84 | +    if (!empty($entry['prefix']) && !empty($entry['address'])) { | 
|  | 85 | +        foreach ($entry['prefix'] as $prefix) { | 
|  | 86 | +            /* new or reassigned takes priority */ | 
|  | 87 | +            $routes[$prefix] = $entry['address']; | 
|  | 88 | +        } | 
|  | 89 | +    } | 
|  | 90 | +} | 
|  | 91 | + | 
|  | 92 | +/* expire all first */ | 
|  | 93 | +foreach (array_keys($routes) as $prefix) { | 
|  | 94 | +    mwexecf('/sbin/route delete -inet6 %s', [$prefix], true); | 
|  | 95 | +} | 
|  | 96 | + | 
|  | 97 | +/* active route apply */ | 
|  | 98 | +foreach ($routes as $prefix => $address) { | 
|  | 99 | +    if (!empty($address)) { | 
|  | 100 | +        mwexecf('/sbin/route add -inet6 %s %s', [$prefix, $address]); | 
|  | 101 | +    } | 
|  | 102 | +} | 
0 commit comments