diff options
| author | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-04-24 01:03:33 +0200 | 
|---|---|---|
| committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-04-24 01:11:33 +0200 | 
| commit | efcfbadb265ced5289f64c76bff777f20565a13e (patch) | |
| tree | 534c70e21a01bef04f3f1e56989b8f7f49206ae3 | |
| parent | 260759dfdebe774aba6866bf49c2928b2242bb7e (diff) | |
| download | libmnl-efcfbadb265ced5289f64c76bff777f20565a13e.tar.gz libmnl-efcfbadb265ced5289f64c76bff777f20565a13e.zip | |
examples: rtnl-route-add improvements (including IPv6 support)
Now, both IPv4 and IPv6 are supported simultaneously in one single file.
While at it:
* I moved the declarations to the beginning of the main function.
* Renamed mask by prefix, which seems more appropriate to me.
* Use RTPROTO_STATIC, as the route has been added by the administrator.
* Set NLM_F_ACK, so we get a report from the kernel about our query and
  treat reply from the kernel.
* Stricter argc checking.
* Use perror instead of printf for error reporting.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
| -rw-r--r-- | examples/rtnl/rtnl-route-add.c | 81 | 
1 files changed, 57 insertions, 24 deletions
| diff --git a/examples/rtnl/rtnl-route-add.c b/examples/rtnl/rtnl-route-add.c index 6d166da..dd810c9 100644 --- a/examples/rtnl/rtnl-route-add.c +++ b/examples/rtnl/rtnl-route-add.c @@ -14,63 +14,83 @@  int main(int argc, char *argv[])  { +	struct mnl_socket *nl; +	char buf[MNL_SOCKET_BUFFER_SIZE]; +	struct nlmsghdr *nlh; +	struct rtmsg *rtm; +	uint32_t prefix, seq, portid; +	union { +		in_addr_t ip; +		struct in6_addr ip6; +	} dst; +	union { +		in_addr_t ip; +		struct in6_addr ip6; +	} gw; +	int iface, ret, family = AF_INET; +  	if (argc <= 3) {  		printf("Usage: %s iface destination cidr [gateway]\n", argv[0]);  		printf("Example: %s eth0 10.0.1.12 32 10.0.1.11\n", argv[0]); +		printf("	 %s eth0 ffff::10.0.1.12 128 fdff::1\n", argv[0]);  		exit(EXIT_FAILURE);  	} -	int iface;  	iface = if_nametoindex(argv[1]);  	if (iface == 0) { -		printf("Bad interface name\n"); +		perror("if_nametoindex");  		exit(EXIT_FAILURE);  	} -	in_addr_t dst;  	if (!inet_pton(AF_INET, argv[2], &dst)) { -		printf("Bad destination\n"); -		exit(EXIT_FAILURE); +		if (!inet_pton(AF_INET6, argv[2], &dst)) { +			perror("inet_pton"); +			exit(EXIT_FAILURE); +		} +		family = AF_INET6;  	} -	uint32_t mask; -	if (sscanf(argv[3], "%u", &mask) == 0) { -		printf("Bad CIDR\n"); +	if (sscanf(argv[3], "%u", &prefix) == 0) { +		perror("sscanf");  		exit(EXIT_FAILURE);  	} -	in_addr_t gw; -	if (argc >= 5 && !inet_pton(AF_INET, argv[4], &gw)) { -		printf("Bad gateway\n"); +	if (argc == 5 && !inet_pton(family, argv[4], &gw)) { +		perror("inet_pton");  		exit(EXIT_FAILURE);  	} -	struct mnl_socket *nl; -	char buf[MNL_SOCKET_BUFFER_SIZE]; -	struct nlmsghdr *nlh; -	struct rtmsg *rtm; -  	nlh = mnl_nlmsg_put_header(buf);  	nlh->nlmsg_type	= RTM_NEWROUTE; -	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; -	nlh->nlmsg_seq = time(NULL); +	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK; +	nlh->nlmsg_seq = seq = time(NULL);  	rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg)); -	rtm->rtm_family = AF_INET; -	rtm->rtm_dst_len = mask; +	rtm->rtm_family = family; +	rtm->rtm_dst_len = prefix;  	rtm->rtm_src_len = 0;  	rtm->rtm_tos = 0; -	rtm->rtm_protocol = RTPROT_BOOT; +	rtm->rtm_protocol = RTPROT_STATIC;  	rtm->rtm_table = RT_TABLE_MAIN;  	rtm->rtm_type = RTN_UNICAST;  	/* is there any gateway? */  	rtm->rtm_scope = (argc == 4) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;  	rtm->rtm_flags = 0; -	mnl_attr_put_u32(nlh, RTA_DST, dst); +	if (family == AF_INET) +		mnl_attr_put_u32(nlh, RTA_DST, dst.ip); +	else +		mnl_attr_put(nlh, RTA_DST, sizeof(struct in6_addr), &dst); +  	mnl_attr_put_u32(nlh, RTA_OIF, iface); -	if (argc >= 5) -		mnl_attr_put_u32(nlh, RTA_GATEWAY, gw); +	if (argc == 5) { +		if (family == AF_INET) +			mnl_attr_put_u32(nlh, RTA_GATEWAY, gw.ip); +		else { +			mnl_attr_put(nlh, RTA_DST, sizeof(struct in6_addr), +					&gw.ip6); +		} +	}  	nl = mnl_socket_open(NETLINK_ROUTE);  	if (nl == NULL) { @@ -82,12 +102,25 @@ int main(int argc, char *argv[])  		perror("mnl_socket_bind");  		exit(EXIT_FAILURE);  	} +	portid = mnl_socket_get_portid(nl);  	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {  		perror("mnl_socket_send");  		exit(EXIT_FAILURE);  	} +	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); +	if (ret < 0) { +		perror("mnl_socket_recvfrom"); +		exit(EXIT_FAILURE); +	} + +	ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); +	if (ret < 0) { +		perror("mnl_cb_run"); +		exit(EXIT_FAILURE); +	} +  	mnl_socket_close(nl);  	return 0; | 
