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, see <http://www.gnu.org/licenses>. 16 */ 17/* 18 * based on ip.c, iproute.c 19 */ 20/* 21 * Authors: 22 * Masahide NAKAMURA @USAGI 23 */ 24 25#include <stdio.h> 26#include <stdlib.h> 27#include <string.h> 28#include <sys/socket.h> 29#include <netinet/icmp6.h> 30 31#include "utils.h" 32#include "ip_common.h" 33 34/* prefix flags; see kernel's net/ipv6/addrconf.c and include/net/if_inet6.h */ 35#define IF_PREFIX_ONLINK 0x01 36#define IF_PREFIX_AUTOCONF 0x02 37 38int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) 39{ 40 FILE *fp = (FILE*)arg; 41 struct prefixmsg *prefix = NLMSG_DATA(n); 42 int len = n->nlmsg_len; 43 struct rtattr * tb[RTA_MAX+1]; 44 int family = preferred_family; 45 46 if (n->nlmsg_type != RTM_NEWPREFIX) { 47 fprintf(stderr, "Not a prefix: %08x %08x %08x\n", 48 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); 49 return 0; 50 } 51 52 len -= NLMSG_LENGTH(sizeof(*prefix)); 53 if (len < 0) { 54 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 55 return -1; 56 } 57 58 if (family == AF_UNSPEC) 59 family = AF_INET6; 60 if (family != AF_INET6) 61 return 0; 62 63 if (prefix->prefix_family != AF_INET6) { 64 fprintf(stderr, "incorrect protocol family: %d\n", prefix->prefix_family); 65 return 0; 66 } 67 if (prefix->prefix_type != ND_OPT_PREFIX_INFORMATION) { 68 fprintf(stderr, "wrong ND type %d\n", prefix->prefix_type); 69 return 0; 70 } 71 72 parse_rtattr(tb, RTA_MAX, RTM_RTA(prefix), len); 73 74 fprintf(fp, "prefix "); 75 76 if (tb[PREFIX_ADDRESS]) { 77 struct in6_addr *pfx; 78 char abuf[256]; 79 80 pfx = (struct in6_addr *)RTA_DATA(tb[PREFIX_ADDRESS]); 81 82 memset(abuf, '\0', sizeof(abuf)); 83 fprintf(fp, "%s", rt_addr_n2a(family, 84 RTA_PAYLOAD(tb[PREFIX_ADDRESS]), 85 pfx, 86 abuf, sizeof(abuf))); 87 } 88 fprintf(fp, "/%u ", prefix->prefix_len); 89 90 fprintf(fp, "dev %s ", ll_index_to_name(prefix->prefix_ifindex)); 91 92 if (prefix->prefix_flags & IF_PREFIX_ONLINK) 93 fprintf(fp, "onlink "); 94 if (prefix->prefix_flags & IF_PREFIX_AUTOCONF) 95 fprintf(fp, "autoconf "); 96 97 if (tb[PREFIX_CACHEINFO]) { 98 struct prefix_cacheinfo *pc; 99 pc = (struct prefix_cacheinfo *)RTA_DATA(tb[PREFIX_CACHEINFO]); 100 101 fprintf(fp, "valid %u ", pc->valid_time); 102 fprintf(fp, "preferred %u ", pc->preferred_time); 103 } 104 105 fprintf(fp, "\n"); 106 fflush(fp); 107 108 return 0; 109} 110