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, 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 
     38 int 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