/*
* Prefix related functions.
* Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <zebra.h>
#include "prefix.h"
#include "vty.h"
#include "sockunion.h"
#include "memory.h"
#include "log.h"
/* Maskbit. */
static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
0xf8, 0xfc, 0xfe, 0xff};
static const struct in6_addr maskbytes6[] =
{
/* /0 */ { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /1 */ { { { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /2 */ { { { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /3 */ { { { 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /4 */ { { { 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /5 */ { { { 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /6 */ { { { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /7 */ { { { 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /8 */ { { { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /9 */ { { { 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /10 */ { { { 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /11 */ { { { 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /12 */ { { { 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /13 */ { { { 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /14 */ { { { 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /15 */ { { { 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /16 */ { { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /17 */ { { { 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /18 */ { { { 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /19 */ { { { 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /20 */ { { { 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /21 */ { { { 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /22 */ { { { 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /23 */ { { { 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /24 */ { { { 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /25 */ { { { 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /26 */ { { { 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /27 */ { { { 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /28 */ { { { 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /29 */ { { { 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /30 */ { { { 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /31 */ { { { 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /32 */ { { { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /33 */ { { { 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /34 */ { { { 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /35 */ { { { 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /36 */ { { { 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /37 */ { { { 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /38 */ { { { 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /39 */ { { { 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /40 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /41 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /42 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /43 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /44 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /45 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /46 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /47 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /48 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /49 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /50 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /51 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /52 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /53 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /54 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /55 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /56 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /57 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /58 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /59 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /60 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /61 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /62 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /63 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /64 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /65 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /66 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /67 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /68 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /69 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /70 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /71 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /72 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /73 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /74 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /75 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /76 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /77 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /78 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /79 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /80 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /81 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /82 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /83 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /84 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /85 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /86 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /87 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /88 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
/* /89 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00 } } },
/* /90 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00 } } },
/* /91 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00 } } },
/* /92 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00 } } },
/* /93 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00 } } },
/* /94 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00 } } },
/* /95 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00 } } },
/* /96 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } },
/* /97 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00 } } },
/* /98 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00 } } },
/* /99 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00 } } },
/* /100 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00 } } },
/* /101 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00 } } },
/* /102 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00 } } },
/* /103 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00 } } },
/* /104 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00 } } },
/* /105 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00 } } },
/* /106 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00 } } },
/* /107 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00 } } },
/* /108 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00 } } },
/* /109 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00 } } },
/* /110 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00 } } },
/* /111 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00 } } },
/* /112 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } } },
/* /113 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00 } } },
/* /114 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00 } } },
/* /115 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00 } } },
/* /116 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00 } } },
/* /117 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00 } } },
/* /118 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00 } } },
/* /119 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00 } } },
/* /120 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 } } },
/* /121 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 } } },
/* /122 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0 } } },
/* /123 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0 } } },
/* /124 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0 } } },
/* /125 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8 } } },
/* /126 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc } } },
/* /127 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe } } },
/* /128 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } }
};
/* Number of bits in prefix type. */
#ifndef PNBBY
#define PNBBY 8
#endif /* PNBBY */
#define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff)
unsigned int
prefix_bit (const u_char *prefix, const u_char prefixlen)
{
unsigned int offset = prefixlen / 8;
unsigned int shift = 7 - (prefixlen % 8);
return (prefix[offset] >> shift) & 1;
}
unsigned int
prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen)
{
return prefix_bit((const u_char *) &prefix->s6_addr, prefixlen);
}
/* Address Famiy Identifier to Address Family converter. */
int
afi2family (afi_t afi)
{
if (afi == AFI_IP)
return AF_INET;
#ifdef HAVE_IPV6
else if (afi == AFI_IP6)
return AF_INET6;
#endif /* HAVE_IPV6 */
return 0;
}
afi_t
family2afi (int family)
{
if (family == AF_INET)
return AFI_IP;
#ifdef HAVE_IPV6
else if (family == AF_INET6)
return AFI_IP6;
#endif /* HAVE_IPV6 */
return 0;
}
/* If n includes p prefix then return 1 else return 0. */
int
prefix_match (const struct prefix *n, const struct prefix *p)
{
int offset;
int shift;
const u_char *np, *pp;
/* If n's prefix is longer than p's one return 0. */
if (n->prefixlen > p->prefixlen)
return 0;
/* Set both prefix's head pointer. */
np = (const u_char *)&n->u.prefix;
pp = (const u_char *)&p->u.prefix;
offset = n->prefixlen / PNBBY;
shift = n->prefixlen % PNBBY;
if (shift)
if (maskbit[shift] & (np[offset] ^ pp[offset]))
return 0;
while (offset--)
if (np[offset] != pp[offset])
return 0;
return 1;
}
/* Copy prefix from src to dest. */
void
prefix_copy (struct prefix *dest, const struct prefix *src)
{
dest->family = src->family;
dest->prefixlen = src->prefixlen;
if (src->family == AF_INET)
dest->u.prefix4 = src->u.prefix4;
#ifdef HAVE_IPV6
else if (src->family == AF_INET6)
dest->u.prefix6 = src->u.prefix6;
#endif /* HAVE_IPV6 */
else if (src->family == AF_UNSPEC)
{
dest->u.lp.id = src->u.lp.id;
dest->u.lp.adv_router = src->u.lp.adv_router;
}
else
{
zlog (NULL, LOG_ERR, "prefix_copy(): Unknown address family %d",
src->family);
assert (0);
}
}
/*
* Return 1 if the address/netmask contained in the prefix structure
* is the same, and else return 0. For this routine, 'same' requires
* that not only the prefix length and the network part be the same,
* but also the host part. Thus, 10.0.0.1/8 and 10.0.0.2/8 are not
* the same. Note that this routine has the same return value sense
* as '==' (which is different from prefix_cmp).
*/
int
prefix_same (const struct prefix *p1, const struct prefix *p2)
{
if (p1->family == p2->family && p1->prefixlen == p2->prefixlen)
{
if (p1->family == AF_INET)
if (IPV4_ADDR_SAME (&p1->u.prefix4.s_addr, &p2->u.prefix4.s_addr))
return 1;
#ifdef HAVE_IPV6
if (p1->family == AF_INET6 )
if (IPV6_ADDR_SAME (&p1->u.prefix6.s6_addr, &p2->u.prefix6.s6_addr))
return 1;
#endif /* HAVE_IPV6 */
}
return 0;
}
/*
* Return 0 if the network prefixes represented by the struct prefix
* arguments are the same prefix, and 1 otherwise. Network prefixes
* are considered the same if the prefix lengths are equal and the
* network parts are the same. Host bits (which are considered masked
* by the prefix length) are not significant. Thus, 10.0.0.1/8 and
* 10.0.0.2/8 are considered equivalent by this routine. Note that
* this routine has the same return sense as strcmp (which is different
* from prefix_same).
*/
int
prefix_cmp (const struct prefix *p1, const struct prefix *p2)
{
int offset;
int shift;
/* Set both prefix's head pointer. */
const u_char *pp1 = (const u_char *)&p1->u.prefix;
const u_char *pp2 = (const u_char *)&p2->u.prefix;
if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)
return 1;
offset = p1->prefixlen / PNBBY;
shift = p1->prefixlen % PNBBY;
if (shift)
if (maskbit[shift] & (pp1[offset] ^ pp2[offset]))
return 1;
while (offset--)
if (pp1[offset] != pp2[offset])
return 1;
return 0;
}
/*
* Count the number of common bits in 2 prefixes. The prefix length is
* ignored for this function; the whole prefix is compared. If the prefix
* address families don't match, return -1; otherwise the return value is
* in range 0 ... maximum prefix length for the address family.
*/
int
prefix_common_bits (const struct prefix *p1, const struct prefix *p2)
{
int pos, bit;
int length = 0;
u_char xor;
/* Set both prefix's head pointer. */
const u_char *pp1 = (const u_char *)&p1->u.prefix;
const u_char *pp2 = (const u_char *)&p2->u.prefix;
if (p1->family == AF_INET)
length = IPV4_MAX_BYTELEN;
#ifdef HAVE_IPV6
if (p1->family == AF_INET6)
length = IPV6_MAX_BYTELEN;
#endif
if (p1->family != p2->family || !length)
return -1;
for (pos = 0; pos < length; pos++)
if (pp1[pos] != pp2[pos])
break;
if (pos == length)
return pos * 8;
xor = pp1[pos] ^ pp2[pos];
for (bit = 0; bit < 8; bit++)
if (xor & (1 << (7 - bit)))
break;
return pos * 8 + bit;
}
/* Return prefix family type string. */
const char *
prefix_family_str (const struct prefix *p)
{
if (p->family == AF_INET)
return "inet";
#ifdef HAVE_IPV6
if (p->family == AF_INET6)
return "inet6";
#endif /* HAVE_IPV6 */
return "unspec";
}
/* Allocate new prefix_ipv4 structure. */
struct prefix_ipv4 *
prefix_ipv4_new ()
{
struct prefix_ipv4 *p;
/* Call prefix_new to allocate a full-size struct prefix to avoid problems
where the struct prefix_ipv4 is cast to struct prefix and unallocated
bytes were being referenced (e.g. in structure assignments). */
p = (struct prefix_ipv4 *)prefix_new();
p->family = AF_INET;
return p;
}
/* Free prefix_ipv4 structure. */
void
prefix_ipv4_free (struct prefix_ipv4 *p)
{
prefix_free((struct prefix *)p);
}
/* When string format is invalid return 0. */
int
str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p)
{
int ret;
int plen;
char *pnt;
char *cp;
/* Find slash inside string. */
pnt = strchr (str, '/');
/* String doesn't contail slash. */
if (pnt == NULL)
{
/* Convert string to prefix. */
ret = inet_aton (str, &p->prefix);
if (ret == 0)
return 0;
/* If address doesn't contain slash we assume it host address. */
p->family = AF_INET;
p->prefixlen = IPV4_MAX_BITLEN;
return ret;
}
else
{
cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
strncpy (cp, str, pnt - str);
*(cp + (pnt - str)) = '\0';
ret = inet_aton (cp, &p->prefix);
XFREE (MTYPE_TMP, cp);
/* Get prefix length. */
plen = (u_char) atoi (++pnt);
if (plen > IPV4_MAX_PREFIXLEN)
return 0;
p->family = AF_INET;
p->prefixlen = plen;
}
return ret;
}
/* Convert masklen into IP address's netmask (network byte order). */
void
masklen2ip (const int masklen, struct in_addr *netmask)
{
assert (masklen >= 0 && masklen <= IPV4_MAX_BITLEN);
/* left shift is only defined for less than the size of the type.
* we unconditionally use long long in case the target platform
* has defined behaviour for << 32 (or has a 64-bit left shift) */
if (sizeof(unsigned long long) > 4)
netmask->s_addr = htonl(0xffffffffULL << (32 - masklen));
else
netmask->s_addr = htonl(masklen ? 0xffffffffU << (32 - masklen) : 0);
}
/* Convert IP address's netmask into integer. We assume netmask is
sequential one. Argument netmask should be network byte order. */
u_char
ip_masklen (struct in_addr netmask)
{
uint32_t tmp = ~ntohl(netmask.s_addr);
if (tmp)
/* clz: count leading zeroes. sadly, the behaviour of this builtin
* is undefined for a 0 argument, even though most CPUs give 32 */
return __builtin_clz(tmp);
else
return 32;
}
/* Apply mask to IPv4 prefix (network byte order). */
void
apply_mask_ipv4 (struct prefix_ipv4 *p)
{
struct in_addr mask;
masklen2ip(p->prefixlen, &mask);
p->prefix.s_addr &= mask.s_addr;
}
/* If prefix is 0.0.0.0/0 then return 1 else return 0. */
int
prefix_ipv4_any (const struct prefix_ipv4 *p)
{
return (p->prefix.s_addr == 0 && p->prefixlen == 0);
}
#ifdef HAVE_IPV6
/* Allocate a new ip version 6 route */
struct prefix_ipv6 *
prefix_ipv6_new (void)
{
struct prefix_ipv6 *p;
/* Allocate a full-size struct prefix to avoid problems with structure
size mismatches. */
p = (struct prefix_ipv6 *)prefix_new();
p->family = AF_INET6;
return p;
}
/* Free prefix for IPv6. */
void
prefix_ipv6_free (struct prefix_ipv6 *p)
{
prefix_free((struct prefix *)p);
}
/* If given string is valid return pin6 else return NULL */
int
str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p)
{
char *pnt;
char *cp;
int ret;
pnt = strchr (str, '/');
/* If string doesn't contain `/' treat it as host route. */
if (pnt == NULL)
{
ret = inet_pton (AF_INET6, str, &p->prefix);
if (ret == 0)
return 0;
p->prefixlen = IPV6_MAX_BITLEN;
}
else
{
int plen;
cp = XMALLOC (0, (pnt - str) + 1);
strncpy (cp, str, pnt - str);
*(cp + (pnt - str)) = '\0';
ret = inet_pton (AF_INET6, cp, &p->prefix);
free (cp);
if (ret == 0)
return 0;
plen = (u_char) atoi (++pnt);
if (plen > IPV6_MAX_BITLEN)
return 0;
p->prefixlen = plen;
}
p->family = AF_INET6;
return ret;
}
/* Convert struct in6_addr netmask into integer.
* FIXME return u_char as ip_maskleni() does. */
int
ip6_masklen (struct in6_addr netmask)
{
int len = 0;
unsigned char val;
unsigned char *pnt;
pnt = (unsigned char *) & netmask;
while ((*pnt == 0xff) && len < IPV6_MAX_BITLEN)
{
len += 8;
pnt++;
}
if (len < IPV6_MAX_BITLEN)
{
val = *pnt;
while (val)
{
len++;
val <<= 1;
}
}
return len;
}
void
masklen2ip6 (const int masklen, struct in6_addr *netmask)
{
assert (masklen >= 0 && masklen <= IPV6_MAX_BITLEN);
memcpy (netmask, maskbytes6 + masklen, sizeof (struct in6_addr));
}
void
apply_mask_ipv6 (struct prefix_ipv6 *p)
{
u_char *pnt;
int index;
int offset;
index = p->prefixlen / 8;
if (index < 16)
{
pnt = (u_char *) &p->prefix;
offset = p->prefixlen % 8;
pnt[index] &= maskbit[offset];
index++;
while (index < 16)
pnt[index++] = 0;
}
}
void
str2in6_addr (const char *str, struct in6_addr *addr)
{
int i;
unsigned int x;
/* %x must point to unsinged int */
for (i = 0; i < 16; i++)
{
sscanf (str + (i * 2), "%02x", &x);
addr->s6_addr[i] = x & 0xff;
}
}
#endif /* HAVE_IPV6 */
void
apply_mask (struct prefix *p)
{
switch (p->family)
{
case AF_INET:
apply_mask_ipv4 ((struct prefix_ipv4 *)p);
break;
#ifdef HAVE_IPV6
case AF_INET6:
apply_mask_ipv6 ((struct prefix_ipv6 *)p);
break;
#endif /* HAVE_IPV6 */
default:
break;
}
return;
}
/* Utility function of convert between struct prefix <=> union sockunion.
* FIXME This function isn't used anywhere. */
struct prefix *
sockunion2prefix (const union sockunion *dest,
const union sockunion *mask)
{
if (dest->sa.sa_family == AF_INET)
{
struct prefix_ipv4 *p;
p = prefix_ipv4_new ();
p->family = AF_INET;
p->prefix = dest->sin.sin_addr;
p->prefixlen = ip_masklen (mask->sin.sin_addr);
return (struct prefix *) p;
}
#ifdef HAVE_IPV6
if (dest->sa.sa_family == AF_INET6)
{
struct prefix_ipv6 *p;
p = prefix_ipv6_new ();
p->family = AF_INET6;
p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);
memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));
return (struct prefix *) p;
}
#endif /* HAVE_IPV6 */
return NULL;
}
/* Utility function of convert between struct prefix <=> union sockunion. */
struct prefix *
sockunion2hostprefix (const union sockunion *su)
{
if (su->sa.sa_family == AF_INET)
{
struct prefix_ipv4 *p;
p = prefix_ipv4_new ();
p->family = AF_INET;
p->prefix = su->sin.sin_addr;
p->prefixlen = IPV4_MAX_BITLEN;
return (struct prefix *) p;
}
#ifdef HAVE_IPV6
if (su->sa.sa_family == AF_INET6)
{
struct prefix_ipv6 *p;
p = prefix_ipv6_new ();
p->family = AF_INET6;
p->prefixlen = IPV6_MAX_BITLEN;
memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr));
return (struct prefix *) p;
}
#endif /* HAVE_IPV6 */
return NULL;
}
void
prefix2sockunion (const struct prefix *p, union sockunion *su)
{
memset (su, 0, sizeof (*su));
su->sa.sa_family = p->family;
if (p->family == AF_INET)
su->sin.sin_addr = p->u.prefix4;
#ifdef HAVE_IPV6
if (p->family == AF_INET6)
memcpy (&su->sin6.sin6_addr, &p->u.prefix6, sizeof (struct in6_addr));
#endif /* HAVE_IPV6 */
}
int
prefix_blen (const struct prefix *p)
{
switch (p->family)
{
case AF_INET:
return IPV4_MAX_BYTELEN;
break;
#ifdef HAVE_IPV6
case AF_INET6:
return IPV6_MAX_BYTELEN;
break;
#endif /* HAVE_IPV6 */
}
return 0;
}
/* Generic function for conversion string to struct prefix. */
int
str2prefix (const char *str, struct prefix *p)
{
int ret;
/* First we try to convert string to struct prefix_ipv4. */
ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p);
if (ret)
return ret;
#ifdef HAVE_IPV6
/* Next we try to convert string to struct prefix_ipv6. */
ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p);
if (ret)
return ret;
#endif /* HAVE_IPV6 */
return 0;
}
int
prefix2str (const struct prefix *p, char *str, int size)
{
char buf[BUFSIZ];
inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
snprintf (str, size, "%s/%d", buf, p->prefixlen);
return 0;
}
struct prefix *
prefix_new ()
{
struct prefix *p;
p = XCALLOC (MTYPE_PREFIX, sizeof *p);
return p;
}
/* Free prefix structure. */
void
prefix_free (struct prefix *p)
{
XFREE (MTYPE_PREFIX, p);
}
/* Utility function. Check the string only contains digit
* character.
* FIXME str.[c|h] would be better place for this function. */
int
all_digit (const char *str)
{
for (; *str != '\0'; str++)
if (!isdigit ((int) *str))
return 0;
return 1;
}
/* Utility function to convert ipv4 prefixes to Classful prefixes */
void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
{
u_int32_t destination;
destination = ntohl (p->prefix.s_addr);
if (p->prefixlen == IPV4_MAX_PREFIXLEN);
/* do nothing for host routes */
else if (IN_CLASSC (destination))
{
p->prefixlen=24;
apply_mask_ipv4(p);
}
else if (IN_CLASSB(destination))
{
p->prefixlen=16;
apply_mask_ipv4(p);
}
else
{
p->prefixlen=8;
apply_mask_ipv4(p);
}
}
in_addr_t
ipv4_network_addr (in_addr_t hostaddr, int masklen)
{
struct in_addr mask;
masklen2ip (masklen, &mask);
return hostaddr & mask.s_addr;
}
in_addr_t
ipv4_broadcast_addr (in_addr_t hostaddr, int masklen)
{
struct in_addr mask;
masklen2ip (masklen, &mask);
return (masklen != IPV4_MAX_PREFIXLEN-1) ?
/* normal case */
(hostaddr | ~mask.s_addr) :
/* special case for /31 */
(hostaddr ^ ~mask.s_addr);
}
/* Utility function to convert ipv4 netmask to prefixes
ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
int
netmask_str2prefix_str (const char *net_str, const char *mask_str,
char *prefix_str)
{
struct in_addr network;
struct in_addr mask;
u_char prefixlen;
u_int32_t destination;
int ret;
ret = inet_aton (net_str, &network);
if (! ret)
return 0;
if (mask_str)
{
ret = inet_aton (mask_str, &mask);
if (! ret)
return 0;
prefixlen = ip_masklen (mask);
}
else
{
destination = ntohl (network.s_addr);
if (network.s_addr == 0)
prefixlen = 0;
else if (IN_CLASSC (destination))
prefixlen = 24;
else if (IN_CLASSB (destination))
prefixlen = 16;
else if (IN_CLASSA (destination))
prefixlen = 8;
else
return 0;
}
sprintf (prefix_str, "%s/%d", net_str, prefixlen);
return 1;
}
#ifdef HAVE_IPV6
/* Utility function for making IPv6 address string. */
const char *
inet6_ntoa (struct in6_addr addr)
{
static char buf[INET6_ADDRSTRLEN];
inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN);
return buf;
}
#endif /* HAVE_IPV6 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>