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