Added netlink error message support to be able to provide return values.

Renamed some structure elements. Updated usage text.
pull/7/head
Oliver Hartkopp 2010-02-21 12:34:34 +00:00
parent 0dc9fcc98e
commit bd1ebaaf28
1 changed files with 46 additions and 20 deletions

66
cangw.c
View File

@ -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);