1/* 2 * Copyright (C)2005 USAGI/WIDE Project 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 */ 18/* 19 * based on ip.c, iproute.c 20 */ 21/* 22 * Authors: 23 * Masahide NAKAMURA @USAGI 24 */ 25 26#include <stdio.h> 27#include <stdlib.h> 28#include <string.h> 29#include <netinet/icmp6.h> 30#include "utils.h" 31 32/* prefix flags; see kernel's net/ipv6/addrconf.c and include/net/if_inet6.h */ 33#define IF_PREFIX_ONLINK 0x01 34#define IF_PREFIX_AUTOCONF 0x02 35 36int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) 37{ 38 FILE *fp = (FILE*)arg; 39 struct prefixmsg *prefix = NLMSG_DATA(n); 40 int len = n->nlmsg_len; 41 struct rtattr * tb[RTA_MAX+1]; 42 int family = preferred_family; 43 44 if (n->nlmsg_type != RTM_NEWPREFIX) { 45 fprintf(stderr, "Not a prefix: %08x %08x %08x\n", 46 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); 47 return 0; 48 } 49 50 len -= NLMSG_LENGTH(sizeof(*prefix)); 51 if (len < 0) { 52 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 53 return -1; 54 } 55 56 if (family == AF_UNSPEC) 57 family = AF_INET6; 58 if (family != AF_INET6) 59 return 0; 60 61 if (prefix->prefix_family != AF_INET6) { 62 fprintf(stderr, "wrong family %d\n", prefix->prefix_family); 63 return 0; 64 } 65 if (prefix->prefix_type != ND_OPT_PREFIX_INFORMATION) { 66 fprintf(stderr, "wrong ND type %d\n", prefix->prefix_type); 67 return 0; 68 } 69 70 parse_rtattr(tb, RTA_MAX, RTM_RTA(prefix), len); 71 72 fprintf(fp, "prefix "); 73 74 if (tb[PREFIX_ADDRESS]) { 75 struct in6_addr *pfx; 76 char abuf[256]; 77 78 pfx = (struct in6_addr *)RTA_DATA(tb[PREFIX_ADDRESS]); 79 80 memset(abuf, '\0', sizeof(abuf)); 81 fprintf(fp, "%s", rt_addr_n2a(family, sizeof(*pfx), pfx, 82 abuf, sizeof(abuf))); 83 } 84 fprintf(fp, "/%u ", prefix->prefix_len); 85 86 fprintf(fp, "dev %s ", ll_index_to_name(prefix->prefix_ifindex)); 87 88 if (prefix->prefix_flags & IF_PREFIX_ONLINK) 89 fprintf(fp, "onlink "); 90 if (prefix->prefix_flags & IF_PREFIX_AUTOCONF) 91 fprintf(fp, "autoconf "); 92 93 if (tb[PREFIX_CACHEINFO]) { 94 struct prefix_cacheinfo *pc; 95 pc = (struct prefix_cacheinfo *)tb[PREFIX_CACHEINFO]; 96 97 fprintf(fp, "valid %u ", pc->valid_time); 98 fprintf(fp, "preferred %u ", pc->preferred_time); 99 } 100 101 fprintf(fp, "\n"); 102 fflush(fp); 103 104 return 0; 105} 106 107