Added netlink error message support to be able to provide return values.
Renamed some structure elements. Updated usage text.pull/7/head
parent
0dc9fcc98e
commit
bd1ebaaf28
66
cangw.c
66
cangw.c
|
|
@ -99,7 +99,7 @@ void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nUsage: %s [options]\n\n", prg);
|
fprintf(stderr, "\nUsage: %s [options]\n\n", prg);
|
||||||
fprintf(stderr, "Commands: -A (add a new rule)\n");
|
fprintf(stderr, "Commands: -A (add a new rule)\n");
|
||||||
fprintf(stderr, " -D (delete a rule) [not yet implemented]\n");
|
fprintf(stderr, " -D (delete a rule)\n");
|
||||||
fprintf(stderr, " -F (flush - delete all rules) [not yet implemented]\n");
|
fprintf(stderr, " -F (flush - delete all rules) [not yet implemented]\n");
|
||||||
fprintf(stderr, " -L (list all rules) [not yet implemented]\n");
|
fprintf(stderr, " -L (list all rules) [not yet implemented]\n");
|
||||||
fprintf(stderr, "Mandatory: -s <src_dev> (source netdevice)\n");
|
fprintf(stderr, "Mandatory: -s <src_dev> (source netdevice)\n");
|
||||||
|
|
@ -209,12 +209,16 @@ int main(int argc, char **argv)
|
||||||
int have_filter = 0;
|
int have_filter = 0;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct nlmsghdr n;
|
struct nlmsghdr nh;
|
||||||
struct rtcanmsg r;
|
struct rtcanmsg rtcan;
|
||||||
char buf[200];
|
char buf[200];
|
||||||
|
|
||||||
} req;
|
} req;
|
||||||
|
|
||||||
|
char rxbuf[8192]; /* netlink receive buffer */
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct nlmsgerr *rte;
|
||||||
|
|
||||||
struct can_filter filter;
|
struct can_filter filter;
|
||||||
struct sockaddr_nl nladdr;
|
struct sockaddr_nl nladdr;
|
||||||
|
|
||||||
|
|
@ -248,19 +252,19 @@ int main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
req.r.src_ifindex = if_nametoindex(optarg);
|
req.rtcan.src_ifindex = if_nametoindex(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
req.r.dst_ifindex = if_nametoindex(optarg);
|
req.rtcan.dst_ifindex = if_nametoindex(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
req.r.can_txflags |= CAN_GW_TXFLAGS_SRC_TSTAMP;
|
req.rtcan.can_txflags |= CAN_GW_TXFLAGS_SRC_TSTAMP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
req.r.can_txflags |= CAN_GW_TXFLAGS_ECHO;
|
req.rtcan.can_txflags |= CAN_GW_TXFLAGS_ECHO;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
|
|
@ -296,7 +300,7 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((argc - optind != 0) || (cmd == UNSPEC) ||
|
if ((argc - optind != 0) || (cmd == UNSPEC) ||
|
||||||
(!req.r.src_ifindex) || (!req.r.dst_ifindex)) {
|
(!req.rtcan.src_ifindex) || (!req.rtcan.dst_ifindex)) {
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
@ -306,13 +310,13 @@ int main(int argc, char **argv)
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
|
||||||
case ADD:
|
case ADD:
|
||||||
req.n.nlmsg_flags = NLM_F_REQUEST;
|
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||||
req.n.nlmsg_type = RTM_NEWROUTE;
|
req.nh.nlmsg_type = RTM_NEWROUTE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEL:
|
case DEL:
|
||||||
req.n.nlmsg_flags = NLM_F_REQUEST;
|
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||||
req.n.nlmsg_type = RTM_DELROUTE;
|
req.nh.nlmsg_type = RTM_DELROUTE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -321,15 +325,15 @@ int main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtcanmsg));
|
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtcanmsg));
|
||||||
req.n.nlmsg_seq = 0;
|
req.nh.nlmsg_seq = 0;
|
||||||
|
|
||||||
req.r.can_family = AF_CAN;
|
req.rtcan.can_family = AF_CAN;
|
||||||
|
|
||||||
/* add new attributes here */
|
/* add new attributes here */
|
||||||
|
|
||||||
if (have_filter)
|
if (have_filter)
|
||||||
addattr_l(&req.n, sizeof(req), CGW_FILTER, &filter, sizeof(filter));
|
addattr_l(&req.nh, sizeof(req), CGW_FILTER, &filter, sizeof(filter));
|
||||||
|
|
||||||
// a better example code
|
// a better example code
|
||||||
// modmsg.modtype = CGW_MOD_ID;
|
// modmsg.modtype = CGW_MOD_ID;
|
||||||
|
|
@ -337,18 +341,40 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
/* add up to CGW_MOD_FUNCS modification definitions */
|
/* add up to CGW_MOD_FUNCS modification definitions */
|
||||||
for (i = 0; i < modidx; i++)
|
for (i = 0; i < modidx; i++)
|
||||||
addattr_l(&req.n, sizeof(req), modmsg[i].instruction, &modmsg[i], CGW_MODATTR_LEN);
|
addattr_l(&req.nh, sizeof(req), modmsg[i].instruction, &modmsg[i], CGW_MODATTR_LEN);
|
||||||
|
|
||||||
memset(&nladdr, 0, sizeof(nladdr));
|
memset(&nladdr, 0, sizeof(nladdr));
|
||||||
nladdr.nl_family = AF_NETLINK;
|
nladdr.nl_family = AF_NETLINK;
|
||||||
nladdr.nl_pid = 0;
|
nladdr.nl_pid = 0;
|
||||||
nladdr.nl_groups = 0;
|
nladdr.nl_groups = 0;
|
||||||
|
|
||||||
err = sendto(s, &req, req.n.nlmsg_len, 0,
|
err = sendto(s, &req, req.nh.nlmsg_len, 0,
|
||||||
(struct sockaddr*)&nladdr, sizeof(nladdr));
|
(struct sockaddr*)&nladdr, sizeof(nladdr));
|
||||||
|
if (err < 0) {
|
||||||
|
perror("netlink sendto");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
if (err < 0)
|
// clean netlink receive buffer
|
||||||
perror("PF_CAN netlink gateway answered ");
|
bzero(rxbuf, sizeof(rxbuf));
|
||||||
|
|
||||||
|
if (cmd == ADD || cmd == DEL) {
|
||||||
|
|
||||||
|
err = recv(s, &rxbuf, sizeof(rxbuf), 0);
|
||||||
|
if (err < 0) {
|
||||||
|
perror("netlink recv");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
nlh = (struct nlmsghdr *)rxbuf;
|
||||||
|
if (nlh->nlmsg_type != NLMSG_ERROR) {
|
||||||
|
fprintf(stderr, "unexpected netlink answer of type %d\n", nlh->nlmsg_type);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
rte = (struct nlmsgerr *)NLMSG_DATA(nlh);
|
||||||
|
err = rte->error;
|
||||||
|
if (err < 0)
|
||||||
|
fprintf(stderr, "netlink error %d (%s)\n", err, strerror(abs(err)));
|
||||||
|
}
|
||||||
|
|
||||||
close(s);
|
close(s);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue