5 #include <netlink/genl/genl.h>
6 #include <netlink/genl/family.h>
7 #include <netlink/genl/ctrl.h>
8 #include <netlink/msg.h>
9 #include <netlink/attr.h>
25 PLINK_ACTION_UNDEFINED
,
31 static int print_mpath_handler(struct nl_msg
*msg
, void *arg
)
33 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
34 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
35 struct nlattr
*pinfo
[NL80211_MPATH_INFO_MAX
+ 1];
36 char dst
[20], next_hop
[20], dev
[20];
37 static struct nla_policy mpath_policy
[NL80211_MPATH_INFO_MAX
+ 1] = {
38 [NL80211_MPATH_INFO_FRAME_QLEN
] = { .type
= NLA_U32
},
39 [NL80211_MPATH_INFO_DSN
] = { .type
= NLA_U32
},
40 [NL80211_MPATH_INFO_METRIC
] = { .type
= NLA_U32
},
41 [NL80211_MPATH_INFO_EXPTIME
] = { .type
= NLA_U32
},
42 [NL80211_MPATH_INFO_DISCOVERY_TIMEOUT
] = { .type
= NLA_U32
},
43 [NL80211_MPATH_INFO_DISCOVERY_RETRIES
] = { .type
= NLA_U8
},
44 [NL80211_MPATH_INFO_FLAGS
] = { .type
= NLA_U8
},
47 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
48 genlmsg_attrlen(gnlh
, 0), NULL
);
51 * TODO: validate the interface and mac address!
52 * Otherwise, there's a race condition as soon as
53 * the kernel starts sending mpath notifications.
56 if (!tb
[NL80211_ATTR_MPATH_INFO
]) {
57 fprintf(stderr
, "mpath info missing!");
60 if (nla_parse_nested(pinfo
, NL80211_MPATH_INFO_MAX
,
61 tb
[NL80211_ATTR_MPATH_INFO
],
63 fprintf(stderr
, "failed to parse nested attributes!");
67 mac_addr_n2a(dst
, nla_data(tb
[NL80211_ATTR_MAC
]));
68 mac_addr_n2a(next_hop
, nla_data(tb
[NL80211_ATTR_MPATH_NEXT_HOP
]));
69 if_indextoname(nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]), dev
);
70 printf("%s %s %s", dst
, next_hop
, dev
);
71 if (pinfo
[NL80211_MPATH_INFO_DSN
])
73 nla_get_u32(pinfo
[NL80211_MPATH_INFO_DSN
]));
74 if (pinfo
[NL80211_MPATH_INFO_METRIC
])
76 nla_get_u32(pinfo
[NL80211_MPATH_INFO_METRIC
]));
77 if (pinfo
[NL80211_MPATH_INFO_FRAME_QLEN
])
79 nla_get_u32(pinfo
[NL80211_MPATH_INFO_FRAME_QLEN
]));
80 if (pinfo
[NL80211_MPATH_INFO_EXPTIME
])
82 nla_get_u32(pinfo
[NL80211_MPATH_INFO_EXPTIME
]));
83 if (pinfo
[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT
])
85 nla_get_u32(pinfo
[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT
]));
86 if (pinfo
[NL80211_MPATH_INFO_DISCOVERY_RETRIES
])
88 nla_get_u8(pinfo
[NL80211_MPATH_INFO_DISCOVERY_RETRIES
]));
89 if (pinfo
[NL80211_MPATH_INFO_FLAGS
])
91 nla_get_u8(pinfo
[NL80211_MPATH_INFO_FLAGS
]));
97 static int handle_mpath_get(struct nl80211_state
*state
,
100 int argc
, char **argv
)
102 unsigned char dst
[ETH_ALEN
];
107 if (mac_addr_a2n(dst
, argv
[0])) {
108 fprintf(stderr
, "invalid mac address\n");
117 NLA_PUT(msg
, NL80211_ATTR_MAC
, ETH_ALEN
, dst
);
119 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_mpath_handler
, NULL
);
125 COMMAND(mpath
, get
, "<MAC address>",
126 NL80211_CMD_GET_MPATH
, 0, CIB_NETDEV
, handle_mpath_get
,
127 "Get information on mesh path to the given node.");
128 COMMAND(mpath
, del
, "<MAC address>",
129 NL80211_CMD_DEL_MPATH
, 0, CIB_NETDEV
, handle_mpath_get
,
130 "Remove the mesh path to the given node.");
132 static int handle_mpath_set(struct nl80211_state
*state
,
135 int argc
, char **argv
)
137 unsigned char dst
[ETH_ALEN
];
138 unsigned char next_hop
[ETH_ALEN
];
143 if (mac_addr_a2n(dst
, argv
[0])) {
144 fprintf(stderr
, "invalid destination mac address\n");
150 if (strcmp("next_hop", argv
[0]) != 0)
155 if (mac_addr_a2n(next_hop
, argv
[0])) {
156 fprintf(stderr
, "invalid next hop mac address\n");
165 NLA_PUT(msg
, NL80211_ATTR_MAC
, ETH_ALEN
, dst
);
166 NLA_PUT(msg
, NL80211_ATTR_MPATH_NEXT_HOP
, ETH_ALEN
, next_hop
);
168 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_mpath_handler
, NULL
);
173 COMMAND(mpath
, new, "<destination MAC address> next_hop <next hop MAC address>",
174 NL80211_CMD_NEW_MPATH
, 0, CIB_NETDEV
, handle_mpath_set
,
175 "Create a new mesh path (instead of relying on automatic discovery).");
176 COMMAND(mpath
, set
, "<destination MAC address> next_hop <next hop MAC address>",
177 NL80211_CMD_SET_MPATH
, 0, CIB_NETDEV
, handle_mpath_set
,
178 "Set an existing mesh path's next hop.");
180 static int handle_mpath_dump(struct nl80211_state
*state
,
183 int argc
, char **argv
)
185 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_mpath_handler
, NULL
);
188 COMMAND(mpath
, dump
, NULL
,
189 NL80211_CMD_GET_MPATH
, NLM_F_DUMP
, CIB_NETDEV
, handle_mpath_dump
,
190 "List known mesh paths.");