xref: /aosp_15_r20/external/ethtool/libmnl/examples/rtnl/rtnl-route-add.c (revision 1b481fc3bb1b45d4cf28d1ec12969dc1055f555d)
1*1b481fc3SMaciej Żenczykowski /* This example is placed in the public domain. */
2*1b481fc3SMaciej Żenczykowski #include <netinet/in.h>
3*1b481fc3SMaciej Żenczykowski #include <arpa/inet.h>
4*1b481fc3SMaciej Żenczykowski #include <time.h>
5*1b481fc3SMaciej Żenczykowski #include <stdio.h>
6*1b481fc3SMaciej Żenczykowski #include <stdlib.h>
7*1b481fc3SMaciej Żenczykowski #include <unistd.h>
8*1b481fc3SMaciej Żenczykowski #include <strings.h>
9*1b481fc3SMaciej Żenczykowski #include <net/if.h>
10*1b481fc3SMaciej Żenczykowski 
11*1b481fc3SMaciej Żenczykowski #include <libmnl/libmnl.h>
12*1b481fc3SMaciej Żenczykowski #include <linux/if_link.h>
13*1b481fc3SMaciej Żenczykowski #include <linux/rtnetlink.h>
14*1b481fc3SMaciej Żenczykowski 
main(int argc,char * argv[])15*1b481fc3SMaciej Żenczykowski int main(int argc, char *argv[])
16*1b481fc3SMaciej Żenczykowski {
17*1b481fc3SMaciej Żenczykowski 	struct mnl_socket *nl;
18*1b481fc3SMaciej Żenczykowski 	char buf[MNL_SOCKET_BUFFER_SIZE];
19*1b481fc3SMaciej Żenczykowski 	struct nlmsghdr *nlh;
20*1b481fc3SMaciej Żenczykowski 	struct rtmsg *rtm;
21*1b481fc3SMaciej Żenczykowski 	uint32_t prefix, seq, portid;
22*1b481fc3SMaciej Żenczykowski 	union {
23*1b481fc3SMaciej Żenczykowski 		in_addr_t ip;
24*1b481fc3SMaciej Żenczykowski 		struct in6_addr ip6;
25*1b481fc3SMaciej Żenczykowski 	} dst;
26*1b481fc3SMaciej Żenczykowski 	union {
27*1b481fc3SMaciej Żenczykowski 		in_addr_t ip;
28*1b481fc3SMaciej Żenczykowski 		struct in6_addr ip6;
29*1b481fc3SMaciej Żenczykowski 	} gw;
30*1b481fc3SMaciej Żenczykowski 	int iface, ret, family = AF_INET;
31*1b481fc3SMaciej Żenczykowski 
32*1b481fc3SMaciej Żenczykowski 	if (argc <= 3) {
33*1b481fc3SMaciej Żenczykowski 		printf("Usage: %s iface destination cidr [gateway]\n", argv[0]);
34*1b481fc3SMaciej Żenczykowski 		printf("Example: %s eth0 10.0.1.12 32 10.0.1.11\n", argv[0]);
35*1b481fc3SMaciej Żenczykowski 		printf("	 %s eth0 ffff::10.0.1.12 128 fdff::1\n", argv[0]);
36*1b481fc3SMaciej Żenczykowski 		exit(EXIT_FAILURE);
37*1b481fc3SMaciej Żenczykowski 	}
38*1b481fc3SMaciej Żenczykowski 
39*1b481fc3SMaciej Żenczykowski 	iface = if_nametoindex(argv[1]);
40*1b481fc3SMaciej Żenczykowski 	if (iface == 0) {
41*1b481fc3SMaciej Żenczykowski 		perror("if_nametoindex");
42*1b481fc3SMaciej Żenczykowski 		exit(EXIT_FAILURE);
43*1b481fc3SMaciej Żenczykowski 	}
44*1b481fc3SMaciej Żenczykowski 
45*1b481fc3SMaciej Żenczykowski 	if (!inet_pton(AF_INET, argv[2], &dst)) {
46*1b481fc3SMaciej Żenczykowski 		if (!inet_pton(AF_INET6, argv[2], &dst)) {
47*1b481fc3SMaciej Żenczykowski 			perror("inet_pton");
48*1b481fc3SMaciej Żenczykowski 			exit(EXIT_FAILURE);
49*1b481fc3SMaciej Żenczykowski 		}
50*1b481fc3SMaciej Żenczykowski 		family = AF_INET6;
51*1b481fc3SMaciej Żenczykowski 	}
52*1b481fc3SMaciej Żenczykowski 
53*1b481fc3SMaciej Żenczykowski 	if (sscanf(argv[3], "%u", &prefix) == 0) {
54*1b481fc3SMaciej Żenczykowski 		perror("sscanf");
55*1b481fc3SMaciej Żenczykowski 		exit(EXIT_FAILURE);
56*1b481fc3SMaciej Żenczykowski 	}
57*1b481fc3SMaciej Żenczykowski 
58*1b481fc3SMaciej Żenczykowski 	if (argc == 5 && !inet_pton(family, argv[4], &gw)) {
59*1b481fc3SMaciej Żenczykowski 		perror("inet_pton");
60*1b481fc3SMaciej Żenczykowski 		exit(EXIT_FAILURE);
61*1b481fc3SMaciej Żenczykowski 	}
62*1b481fc3SMaciej Żenczykowski 
63*1b481fc3SMaciej Żenczykowski 	nlh = mnl_nlmsg_put_header(buf);
64*1b481fc3SMaciej Żenczykowski 	nlh->nlmsg_type	= RTM_NEWROUTE;
65*1b481fc3SMaciej Żenczykowski 	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
66*1b481fc3SMaciej Żenczykowski 	nlh->nlmsg_seq = seq = time(NULL);
67*1b481fc3SMaciej Żenczykowski 
68*1b481fc3SMaciej Żenczykowski 	rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg));
69*1b481fc3SMaciej Żenczykowski 	rtm->rtm_family = family;
70*1b481fc3SMaciej Żenczykowski 	rtm->rtm_dst_len = prefix;
71*1b481fc3SMaciej Żenczykowski 	rtm->rtm_src_len = 0;
72*1b481fc3SMaciej Żenczykowski 	rtm->rtm_tos = 0;
73*1b481fc3SMaciej Żenczykowski 	rtm->rtm_protocol = RTPROT_STATIC;
74*1b481fc3SMaciej Żenczykowski 	rtm->rtm_table = RT_TABLE_MAIN;
75*1b481fc3SMaciej Żenczykowski 	rtm->rtm_type = RTN_UNICAST;
76*1b481fc3SMaciej Żenczykowski 	/* is there any gateway? */
77*1b481fc3SMaciej Żenczykowski 	rtm->rtm_scope = (argc == 4) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
78*1b481fc3SMaciej Żenczykowski 	rtm->rtm_flags = 0;
79*1b481fc3SMaciej Żenczykowski 
80*1b481fc3SMaciej Żenczykowski 	if (family == AF_INET)
81*1b481fc3SMaciej Żenczykowski 		mnl_attr_put_u32(nlh, RTA_DST, dst.ip);
82*1b481fc3SMaciej Żenczykowski 	else
83*1b481fc3SMaciej Żenczykowski 		mnl_attr_put(nlh, RTA_DST, sizeof(struct in6_addr), &dst);
84*1b481fc3SMaciej Żenczykowski 
85*1b481fc3SMaciej Żenczykowski 	mnl_attr_put_u32(nlh, RTA_OIF, iface);
86*1b481fc3SMaciej Żenczykowski 	if (argc == 5) {
87*1b481fc3SMaciej Żenczykowski 		if (family == AF_INET)
88*1b481fc3SMaciej Żenczykowski 			mnl_attr_put_u32(nlh, RTA_GATEWAY, gw.ip);
89*1b481fc3SMaciej Żenczykowski 		else {
90*1b481fc3SMaciej Żenczykowski 			mnl_attr_put(nlh, RTA_GATEWAY, sizeof(struct in6_addr),
91*1b481fc3SMaciej Żenczykowski 					&gw.ip6);
92*1b481fc3SMaciej Żenczykowski 		}
93*1b481fc3SMaciej Żenczykowski 	}
94*1b481fc3SMaciej Żenczykowski 
95*1b481fc3SMaciej Żenczykowski 	nl = mnl_socket_open(NETLINK_ROUTE);
96*1b481fc3SMaciej Żenczykowski 	if (nl == NULL) {
97*1b481fc3SMaciej Żenczykowski 		perror("mnl_socket_open");
98*1b481fc3SMaciej Żenczykowski 		exit(EXIT_FAILURE);
99*1b481fc3SMaciej Żenczykowski 	}
100*1b481fc3SMaciej Żenczykowski 
101*1b481fc3SMaciej Żenczykowski 	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
102*1b481fc3SMaciej Żenczykowski 		perror("mnl_socket_bind");
103*1b481fc3SMaciej Żenczykowski 		exit(EXIT_FAILURE);
104*1b481fc3SMaciej Żenczykowski 	}
105*1b481fc3SMaciej Żenczykowski 	portid = mnl_socket_get_portid(nl);
106*1b481fc3SMaciej Żenczykowski 
107*1b481fc3SMaciej Żenczykowski 	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
108*1b481fc3SMaciej Żenczykowski 		perror("mnl_socket_sendto");
109*1b481fc3SMaciej Żenczykowski 		exit(EXIT_FAILURE);
110*1b481fc3SMaciej Żenczykowski 	}
111*1b481fc3SMaciej Żenczykowski 
112*1b481fc3SMaciej Żenczykowski 	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
113*1b481fc3SMaciej Żenczykowski 	if (ret < 0) {
114*1b481fc3SMaciej Żenczykowski 		perror("mnl_socket_recvfrom");
115*1b481fc3SMaciej Żenczykowski 		exit(EXIT_FAILURE);
116*1b481fc3SMaciej Żenczykowski 	}
117*1b481fc3SMaciej Żenczykowski 
118*1b481fc3SMaciej Żenczykowski 	ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
119*1b481fc3SMaciej Żenczykowski 	if (ret < 0) {
120*1b481fc3SMaciej Żenczykowski 		perror("mnl_cb_run");
121*1b481fc3SMaciej Żenczykowski 		exit(EXIT_FAILURE);
122*1b481fc3SMaciej Żenczykowski 	}
123*1b481fc3SMaciej Żenczykowski 
124*1b481fc3SMaciej Żenczykowski 	mnl_socket_close(nl);
125*1b481fc3SMaciej Żenczykowski 
126*1b481fc3SMaciej Żenczykowski 	return 0;
127*1b481fc3SMaciej Żenczykowski }
128