Home | History | Annotate | Download | only in ip
      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 
     36 int 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