xref: /aosp_15_r20/external/ethtool/netlink/permaddr.c (revision 1b481fc3bb1b45d4cf28d1ec12969dc1055f555d)
1*1b481fc3SMaciej Żenczykowski /*
2*1b481fc3SMaciej Żenczykowski  * permaddr.c - netlink implementation of permanent address request
3*1b481fc3SMaciej Żenczykowski  *
4*1b481fc3SMaciej Żenczykowski  * Implementation of "ethtool -P <dev>"
5*1b481fc3SMaciej Żenczykowski  */
6*1b481fc3SMaciej Żenczykowski 
7*1b481fc3SMaciej Żenczykowski #include <errno.h>
8*1b481fc3SMaciej Żenczykowski #include <string.h>
9*1b481fc3SMaciej Żenczykowski #include <stdio.h>
10*1b481fc3SMaciej Żenczykowski #include <linux/rtnetlink.h>
11*1b481fc3SMaciej Żenczykowski #include <linux/if_link.h>
12*1b481fc3SMaciej Żenczykowski 
13*1b481fc3SMaciej Żenczykowski #include "../internal.h"
14*1b481fc3SMaciej Żenczykowski #include "../common.h"
15*1b481fc3SMaciej Żenczykowski #include "netlink.h"
16*1b481fc3SMaciej Żenczykowski 
17*1b481fc3SMaciej Żenczykowski /* PERMADDR_GET */
18*1b481fc3SMaciej Żenczykowski 
permaddr_prep_request(struct nl_socket * nlsk)19*1b481fc3SMaciej Żenczykowski static int permaddr_prep_request(struct nl_socket *nlsk)
20*1b481fc3SMaciej Żenczykowski {
21*1b481fc3SMaciej Żenczykowski 	unsigned int nlm_flags = NLM_F_REQUEST | NLM_F_ACK;
22*1b481fc3SMaciej Żenczykowski 	struct nl_context *nlctx = nlsk->nlctx;
23*1b481fc3SMaciej Żenczykowski 	const char *devname = nlctx->ctx->devname;
24*1b481fc3SMaciej Żenczykowski 	struct nl_msg_buff *msgbuff = &nlsk->msgbuff;
25*1b481fc3SMaciej Żenczykowski 	struct ifinfomsg *ifinfo;
26*1b481fc3SMaciej Żenczykowski 	struct nlmsghdr *nlhdr;
27*1b481fc3SMaciej Żenczykowski 	int ret;
28*1b481fc3SMaciej Żenczykowski 
29*1b481fc3SMaciej Żenczykowski 	if (devname && !strcmp(devname, WILDCARD_DEVNAME)) {
30*1b481fc3SMaciej Żenczykowski 		devname = NULL;
31*1b481fc3SMaciej Żenczykowski 		nlm_flags |= NLM_F_DUMP;
32*1b481fc3SMaciej Żenczykowski 	}
33*1b481fc3SMaciej Żenczykowski 	nlctx->is_dump = !devname;
34*1b481fc3SMaciej Żenczykowski 
35*1b481fc3SMaciej Żenczykowski         ret = msgbuff_realloc(msgbuff, MNL_SOCKET_BUFFER_SIZE);
36*1b481fc3SMaciej Żenczykowski         if (ret < 0)
37*1b481fc3SMaciej Żenczykowski                 return ret;
38*1b481fc3SMaciej Żenczykowski         memset(msgbuff->buff, '\0', NLMSG_HDRLEN + sizeof(*ifinfo));
39*1b481fc3SMaciej Żenczykowski 
40*1b481fc3SMaciej Żenczykowski 	nlhdr = mnl_nlmsg_put_header(msgbuff->buff);
41*1b481fc3SMaciej Żenczykowski 	nlhdr->nlmsg_type = RTM_GETLINK;
42*1b481fc3SMaciej Żenczykowski 	nlhdr->nlmsg_flags = nlm_flags;
43*1b481fc3SMaciej Żenczykowski 	msgbuff->nlhdr = nlhdr;
44*1b481fc3SMaciej Żenczykowski 	ifinfo = mnl_nlmsg_put_extra_header(nlhdr, sizeof(*ifinfo));
45*1b481fc3SMaciej Żenczykowski 
46*1b481fc3SMaciej Żenczykowski 	if (devname) {
47*1b481fc3SMaciej Żenczykowski 		uint16_t type = IFLA_IFNAME;
48*1b481fc3SMaciej Żenczykowski 
49*1b481fc3SMaciej Żenczykowski 		if (strlen(devname) >= IFNAMSIZ)
50*1b481fc3SMaciej Żenczykowski 			type = IFLA_ALT_IFNAME;
51*1b481fc3SMaciej Żenczykowski 		if (ethnla_put_strz(msgbuff, type, devname))
52*1b481fc3SMaciej Żenczykowski 			return -EMSGSIZE;
53*1b481fc3SMaciej Żenczykowski 	}
54*1b481fc3SMaciej Żenczykowski 	if (ethnla_put_u32(msgbuff, IFLA_EXT_MASK, RTEXT_FILTER_SKIP_STATS))
55*1b481fc3SMaciej Żenczykowski 		return -EMSGSIZE;
56*1b481fc3SMaciej Żenczykowski 
57*1b481fc3SMaciej Żenczykowski 	return 0;
58*1b481fc3SMaciej Żenczykowski }
59*1b481fc3SMaciej Żenczykowski 
permaddr_reply_cb(const struct nlmsghdr * nlhdr,void * data)60*1b481fc3SMaciej Żenczykowski int permaddr_reply_cb(const struct nlmsghdr *nlhdr, void *data)
61*1b481fc3SMaciej Żenczykowski {
62*1b481fc3SMaciej Żenczykowski 	const struct nlattr *tb[__IFLA_MAX] = {};
63*1b481fc3SMaciej Żenczykowski 	DECLARE_ATTR_TB_INFO(tb);
64*1b481fc3SMaciej Żenczykowski 	struct nl_context *nlctx = data;
65*1b481fc3SMaciej Żenczykowski 	const uint8_t *permaddr;
66*1b481fc3SMaciej Żenczykowski 	unsigned int i;
67*1b481fc3SMaciej Żenczykowski 	int ret;
68*1b481fc3SMaciej Żenczykowski 
69*1b481fc3SMaciej Żenczykowski 	if (nlhdr->nlmsg_type != RTM_NEWLINK)
70*1b481fc3SMaciej Żenczykowski 		goto err;
71*1b481fc3SMaciej Żenczykowski 	ret = mnl_attr_parse(nlhdr, sizeof(struct ifinfomsg), attr_cb,
72*1b481fc3SMaciej Żenczykowski 			     &tb_info);
73*1b481fc3SMaciej Żenczykowski 	if (ret < 0 || !tb[IFLA_IFNAME])
74*1b481fc3SMaciej Żenczykowski 		goto err;
75*1b481fc3SMaciej Żenczykowski 	nlctx->devname = mnl_attr_get_str(tb[IFLA_IFNAME]);
76*1b481fc3SMaciej Żenczykowski 	if (!dev_ok(nlctx))
77*1b481fc3SMaciej Żenczykowski 		goto err;
78*1b481fc3SMaciej Żenczykowski 
79*1b481fc3SMaciej Żenczykowski 	if (!tb[IFLA_PERM_ADDRESS]) {
80*1b481fc3SMaciej Żenczykowski 		if (!nlctx->is_dump)
81*1b481fc3SMaciej Żenczykowski 			printf("Permanent address: not set\n");
82*1b481fc3SMaciej Żenczykowski 		return MNL_CB_OK;
83*1b481fc3SMaciej Żenczykowski 	}
84*1b481fc3SMaciej Żenczykowski 
85*1b481fc3SMaciej Żenczykowski 	if (nlctx->is_dump)
86*1b481fc3SMaciej Żenczykowski 		printf("Permanent address of %s:", nlctx->devname);
87*1b481fc3SMaciej Żenczykowski 	else
88*1b481fc3SMaciej Żenczykowski 		printf("Permanent address:");
89*1b481fc3SMaciej Żenczykowski 	permaddr = mnl_attr_get_payload(tb[IFLA_PERM_ADDRESS]);
90*1b481fc3SMaciej Żenczykowski 	for (i = 0; i < mnl_attr_get_payload_len(tb[IFLA_PERM_ADDRESS]); i++)
91*1b481fc3SMaciej Żenczykowski 		printf("%c%02x", i ? ':' : ' ', permaddr[i]);
92*1b481fc3SMaciej Żenczykowski 	putchar('\n');
93*1b481fc3SMaciej Żenczykowski 	return MNL_CB_OK;
94*1b481fc3SMaciej Żenczykowski 
95*1b481fc3SMaciej Żenczykowski err:
96*1b481fc3SMaciej Żenczykowski 	if (nlctx->is_dump || nlctx->is_monitor)
97*1b481fc3SMaciej Żenczykowski 		return MNL_CB_OK;
98*1b481fc3SMaciej Żenczykowski 	nlctx->exit_code = 2;
99*1b481fc3SMaciej Żenczykowski 	return MNL_CB_ERROR;
100*1b481fc3SMaciej Żenczykowski }
101*1b481fc3SMaciej Żenczykowski 
nl_permaddr(struct cmd_context * ctx)102*1b481fc3SMaciej Żenczykowski int nl_permaddr(struct cmd_context *ctx)
103*1b481fc3SMaciej Żenczykowski {
104*1b481fc3SMaciej Żenczykowski 	struct nl_context *nlctx = ctx->nlctx;
105*1b481fc3SMaciej Żenczykowski 	int ret;
106*1b481fc3SMaciej Żenczykowski 
107*1b481fc3SMaciej Żenczykowski 	ret = netlink_init_rtnl_socket(nlctx);
108*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
109*1b481fc3SMaciej Żenczykowski 		return ret;
110*1b481fc3SMaciej Żenczykowski 	ret = permaddr_prep_request(nlctx->rtnl_socket);
111*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
112*1b481fc3SMaciej Żenczykowski 		return ret;
113*1b481fc3SMaciej Żenczykowski 	return nlsock_send_get_request(nlctx->rtnl_socket, permaddr_reply_cb);
114*1b481fc3SMaciej Żenczykowski }
115