aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-07-12 11:18:45 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-12 11:18:45 -0400
commit10b0a7732e04aeb7e21fe7dc3b8249a3041eab28 (patch)
tree01faf58d03868e684bc784ab44e5f7714e8d7ee3
parentd3bd3a5eeb087bf6a06e9bdfc589096608f933a0 (diff)
parent5d91efa8dd8ced8647798d067f2ac8125194be58 (diff)
Merge branch 'for-davem' of git://gitorious.org/linux-can/linux-can-next
-rw-r--r--net/can/gw.c90
1 files changed, 33 insertions, 57 deletions
diff --git a/net/can/gw.c b/net/can/gw.c
index b41acf25668f..b54d5e695b03 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -444,11 +444,14 @@ static int cgw_notifier(struct notifier_block *nb,
444 return NOTIFY_DONE; 444 return NOTIFY_DONE;
445} 445}
446 446
447static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj) 447static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type,
448 u32 pid, u32 seq, int flags)
448{ 449{
449 struct cgw_frame_mod mb; 450 struct cgw_frame_mod mb;
450 struct rtcanmsg *rtcan; 451 struct rtcanmsg *rtcan;
451 struct nlmsghdr *nlh = nlmsg_put(skb, 0, 0, 0, sizeof(*rtcan), 0); 452 struct nlmsghdr *nlh;
453
454 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtcan), flags);
452 if (!nlh) 455 if (!nlh)
453 return -EMSGSIZE; 456 return -EMSGSIZE;
454 457
@@ -462,15 +465,11 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj)
462 if (gwj->handled_frames) { 465 if (gwj->handled_frames) {
463 if (nla_put_u32(skb, CGW_HANDLED, gwj->handled_frames) < 0) 466 if (nla_put_u32(skb, CGW_HANDLED, gwj->handled_frames) < 0)
464 goto cancel; 467 goto cancel;
465 else
466 nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32));
467 } 468 }
468 469
469 if (gwj->dropped_frames) { 470 if (gwj->dropped_frames) {
470 if (nla_put_u32(skb, CGW_DROPPED, gwj->dropped_frames) < 0) 471 if (nla_put_u32(skb, CGW_DROPPED, gwj->dropped_frames) < 0)
471 goto cancel; 472 goto cancel;
472 else
473 nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32));
474 } 473 }
475 474
476 /* check non default settings of attributes */ 475 /* check non default settings of attributes */
@@ -480,8 +479,6 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj)
480 mb.modtype = gwj->mod.modtype.and; 479 mb.modtype = gwj->mod.modtype.and;
481 if (nla_put(skb, CGW_MOD_AND, sizeof(mb), &mb) < 0) 480 if (nla_put(skb, CGW_MOD_AND, sizeof(mb), &mb) < 0)
482 goto cancel; 481 goto cancel;
483 else
484 nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb));
485 } 482 }
486 483
487 if (gwj->mod.modtype.or) { 484 if (gwj->mod.modtype.or) {
@@ -489,8 +486,6 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj)
489 mb.modtype = gwj->mod.modtype.or; 486 mb.modtype = gwj->mod.modtype.or;
490 if (nla_put(skb, CGW_MOD_OR, sizeof(mb), &mb) < 0) 487 if (nla_put(skb, CGW_MOD_OR, sizeof(mb), &mb) < 0)
491 goto cancel; 488 goto cancel;
492 else
493 nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb));
494 } 489 }
495 490
496 if (gwj->mod.modtype.xor) { 491 if (gwj->mod.modtype.xor) {
@@ -498,8 +493,6 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj)
498 mb.modtype = gwj->mod.modtype.xor; 493 mb.modtype = gwj->mod.modtype.xor;
499 if (nla_put(skb, CGW_MOD_XOR, sizeof(mb), &mb) < 0) 494 if (nla_put(skb, CGW_MOD_XOR, sizeof(mb), &mb) < 0)
500 goto cancel; 495 goto cancel;
501 else
502 nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb));
503 } 496 }
504 497
505 if (gwj->mod.modtype.set) { 498 if (gwj->mod.modtype.set) {
@@ -507,26 +500,18 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj)
507 mb.modtype = gwj->mod.modtype.set; 500 mb.modtype = gwj->mod.modtype.set;
508 if (nla_put(skb, CGW_MOD_SET, sizeof(mb), &mb) < 0) 501 if (nla_put(skb, CGW_MOD_SET, sizeof(mb), &mb) < 0)
509 goto cancel; 502 goto cancel;
510 else
511 nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb));
512 } 503 }
513 504
514 if (gwj->mod.csumfunc.crc8) { 505 if (gwj->mod.csumfunc.crc8) {
515 if (nla_put(skb, CGW_CS_CRC8, CGW_CS_CRC8_LEN, 506 if (nla_put(skb, CGW_CS_CRC8, CGW_CS_CRC8_LEN,
516 &gwj->mod.csum.crc8) < 0) 507 &gwj->mod.csum.crc8) < 0)
517 goto cancel; 508 goto cancel;
518 else
519 nlh->nlmsg_len += NLA_HDRLEN + \
520 NLA_ALIGN(CGW_CS_CRC8_LEN);
521 } 509 }
522 510
523 if (gwj->mod.csumfunc.xor) { 511 if (gwj->mod.csumfunc.xor) {
524 if (nla_put(skb, CGW_CS_XOR, CGW_CS_XOR_LEN, 512 if (nla_put(skb, CGW_CS_XOR, CGW_CS_XOR_LEN,
525 &gwj->mod.csum.xor) < 0) 513 &gwj->mod.csum.xor) < 0)
526 goto cancel; 514 goto cancel;
527 else
528 nlh->nlmsg_len += NLA_HDRLEN + \
529 NLA_ALIGN(CGW_CS_XOR_LEN);
530 } 515 }
531 516
532 if (gwj->gwtype == CGW_TYPE_CAN_CAN) { 517 if (gwj->gwtype == CGW_TYPE_CAN_CAN) {
@@ -535,23 +520,16 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj)
535 if (nla_put(skb, CGW_FILTER, sizeof(struct can_filter), 520 if (nla_put(skb, CGW_FILTER, sizeof(struct can_filter),
536 &gwj->ccgw.filter) < 0) 521 &gwj->ccgw.filter) < 0)
537 goto cancel; 522 goto cancel;
538 else
539 nlh->nlmsg_len += NLA_HDRLEN +
540 NLA_ALIGN(sizeof(struct can_filter));
541 } 523 }
542 524
543 if (nla_put_u32(skb, CGW_SRC_IF, gwj->ccgw.src_idx) < 0) 525 if (nla_put_u32(skb, CGW_SRC_IF, gwj->ccgw.src_idx) < 0)
544 goto cancel; 526 goto cancel;
545 else
546 nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32));
547 527
548 if (nla_put_u32(skb, CGW_DST_IF, gwj->ccgw.dst_idx) < 0) 528 if (nla_put_u32(skb, CGW_DST_IF, gwj->ccgw.dst_idx) < 0)
549 goto cancel; 529 goto cancel;
550 else
551 nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32));
552 } 530 }
553 531
554 return skb->len; 532 return nlmsg_end(skb, nlh);
555 533
556cancel: 534cancel:
557 nlmsg_cancel(skb, nlh); 535 nlmsg_cancel(skb, nlh);
@@ -571,7 +549,8 @@ static int cgw_dump_jobs(struct sk_buff *skb, struct netlink_callback *cb)
571 if (idx < s_idx) 549 if (idx < s_idx)
572 goto cont; 550 goto cont;
573 551
574 if (cgw_put_job(skb, gwj) < 0) 552 if (cgw_put_job(skb, gwj, RTM_NEWROUTE, NETLINK_CB(cb->skb).pid,
553 cb->nlh->nlmsg_seq, NLM_F_MULTI) < 0)
575 break; 554 break;
576cont: 555cont:
577 idx++; 556 idx++;
@@ -583,6 +562,18 @@ cont:
583 return skb->len; 562 return skb->len;
584} 563}
585 564
565static const struct nla_policy cgw_policy[CGW_MAX+1] = {
566 [CGW_MOD_AND] = { .len = sizeof(struct cgw_frame_mod) },
567 [CGW_MOD_OR] = { .len = sizeof(struct cgw_frame_mod) },
568 [CGW_MOD_XOR] = { .len = sizeof(struct cgw_frame_mod) },
569 [CGW_MOD_SET] = { .len = sizeof(struct cgw_frame_mod) },
570 [CGW_CS_XOR] = { .len = sizeof(struct cgw_csum_xor) },
571 [CGW_CS_CRC8] = { .len = sizeof(struct cgw_csum_crc8) },
572 [CGW_SRC_IF] = { .type = NLA_U32 },
573 [CGW_DST_IF] = { .type = NLA_U32 },
574 [CGW_FILTER] = { .len = sizeof(struct can_filter) },
575};
576
586/* check for common and gwtype specific attributes */ 577/* check for common and gwtype specific attributes */
587static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, 578static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
588 u8 gwtype, void *gwtypeattr) 579 u8 gwtype, void *gwtypeattr)
@@ -595,14 +586,14 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
595 /* initialize modification & checksum data space */ 586 /* initialize modification & checksum data space */
596 memset(mod, 0, sizeof(*mod)); 587 memset(mod, 0, sizeof(*mod));
597 588
598 err = nlmsg_parse(nlh, sizeof(struct rtcanmsg), tb, CGW_MAX, NULL); 589 err = nlmsg_parse(nlh, sizeof(struct rtcanmsg), tb, CGW_MAX,
590 cgw_policy);
599 if (err < 0) 591 if (err < 0)
600 return err; 592 return err;
601 593
602 /* check for AND/OR/XOR/SET modifications */ 594 /* check for AND/OR/XOR/SET modifications */
603 595
604 if (tb[CGW_MOD_AND] && 596 if (tb[CGW_MOD_AND]) {
605 nla_len(tb[CGW_MOD_AND]) == CGW_MODATTR_LEN) {
606 nla_memcpy(&mb, tb[CGW_MOD_AND], CGW_MODATTR_LEN); 597 nla_memcpy(&mb, tb[CGW_MOD_AND], CGW_MODATTR_LEN);
607 598
608 canframecpy(&mod->modframe.and, &mb.cf); 599 canframecpy(&mod->modframe.and, &mb.cf);
@@ -618,8 +609,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
618 mod->modfunc[modidx++] = mod_and_data; 609 mod->modfunc[modidx++] = mod_and_data;
619 } 610 }
620 611
621 if (tb[CGW_MOD_OR] && 612 if (tb[CGW_MOD_OR]) {
622 nla_len(tb[CGW_MOD_OR]) == CGW_MODATTR_LEN) {
623 nla_memcpy(&mb, tb[CGW_MOD_OR], CGW_MODATTR_LEN); 613 nla_memcpy(&mb, tb[CGW_MOD_OR], CGW_MODATTR_LEN);
624 614
625 canframecpy(&mod->modframe.or, &mb.cf); 615 canframecpy(&mod->modframe.or, &mb.cf);
@@ -635,8 +625,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
635 mod->modfunc[modidx++] = mod_or_data; 625 mod->modfunc[modidx++] = mod_or_data;
636 } 626 }
637 627
638 if (tb[CGW_MOD_XOR] && 628 if (tb[CGW_MOD_XOR]) {
639 nla_len(tb[CGW_MOD_XOR]) == CGW_MODATTR_LEN) {
640 nla_memcpy(&mb, tb[CGW_MOD_XOR], CGW_MODATTR_LEN); 629 nla_memcpy(&mb, tb[CGW_MOD_XOR], CGW_MODATTR_LEN);
641 630
642 canframecpy(&mod->modframe.xor, &mb.cf); 631 canframecpy(&mod->modframe.xor, &mb.cf);
@@ -652,8 +641,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
652 mod->modfunc[modidx++] = mod_xor_data; 641 mod->modfunc[modidx++] = mod_xor_data;
653 } 642 }
654 643
655 if (tb[CGW_MOD_SET] && 644 if (tb[CGW_MOD_SET]) {
656 nla_len(tb[CGW_MOD_SET]) == CGW_MODATTR_LEN) {
657 nla_memcpy(&mb, tb[CGW_MOD_SET], CGW_MODATTR_LEN); 645 nla_memcpy(&mb, tb[CGW_MOD_SET], CGW_MODATTR_LEN);
658 646
659 canframecpy(&mod->modframe.set, &mb.cf); 647 canframecpy(&mod->modframe.set, &mb.cf);
@@ -672,11 +660,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
672 /* check for checksum operations after CAN frame modifications */ 660 /* check for checksum operations after CAN frame modifications */
673 if (modidx) { 661 if (modidx) {
674 662
675 if (tb[CGW_CS_CRC8] && 663 if (tb[CGW_CS_CRC8]) {
676 nla_len(tb[CGW_CS_CRC8]) == CGW_CS_CRC8_LEN) { 664 struct cgw_csum_crc8 *c = nla_data(tb[CGW_CS_CRC8]);
677
678 struct cgw_csum_crc8 *c = (struct cgw_csum_crc8 *)\
679 nla_data(tb[CGW_CS_CRC8]);
680 665
681 err = cgw_chk_csum_parms(c->from_idx, c->to_idx, 666 err = cgw_chk_csum_parms(c->from_idx, c->to_idx,
682 c->result_idx); 667 c->result_idx);
@@ -699,11 +684,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
699 mod->csumfunc.crc8 = cgw_csum_crc8_neg; 684 mod->csumfunc.crc8 = cgw_csum_crc8_neg;
700 } 685 }
701 686
702 if (tb[CGW_CS_XOR] && 687 if (tb[CGW_CS_XOR]) {
703 nla_len(tb[CGW_CS_XOR]) == CGW_CS_XOR_LEN) { 688 struct cgw_csum_xor *c = nla_data(tb[CGW_CS_XOR]);
704
705 struct cgw_csum_xor *c = (struct cgw_csum_xor *)\
706 nla_data(tb[CGW_CS_XOR]);
707 689
708 err = cgw_chk_csum_parms(c->from_idx, c->to_idx, 690 err = cgw_chk_csum_parms(c->from_idx, c->to_idx,
709 c->result_idx); 691 c->result_idx);
@@ -735,8 +717,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
735 memset(ccgw, 0, sizeof(*ccgw)); 717 memset(ccgw, 0, sizeof(*ccgw));
736 718
737 /* check for can_filter in attributes */ 719 /* check for can_filter in attributes */
738 if (tb[CGW_FILTER] && 720 if (tb[CGW_FILTER])
739 nla_len(tb[CGW_FILTER]) == sizeof(struct can_filter))
740 nla_memcpy(&ccgw->filter, tb[CGW_FILTER], 721 nla_memcpy(&ccgw->filter, tb[CGW_FILTER],
741 sizeof(struct can_filter)); 722 sizeof(struct can_filter));
742 723
@@ -746,13 +727,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
746 if (!tb[CGW_SRC_IF] || !tb[CGW_DST_IF]) 727 if (!tb[CGW_SRC_IF] || !tb[CGW_DST_IF])
747 return err; 728 return err;
748 729
749 if (nla_len(tb[CGW_SRC_IF]) == sizeof(u32)) 730 ccgw->src_idx = nla_get_u32(tb[CGW_SRC_IF]);
750 nla_memcpy(&ccgw->src_idx, tb[CGW_SRC_IF], 731 ccgw->dst_idx = nla_get_u32(tb[CGW_DST_IF]);
751 sizeof(u32));
752
753 if (nla_len(tb[CGW_DST_IF]) == sizeof(u32))
754 nla_memcpy(&ccgw->dst_idx, tb[CGW_DST_IF],
755 sizeof(u32));
756 732
757 /* both indices set to 0 for flushing all routing entries */ 733 /* both indices set to 0 for flushing all routing entries */
758 if (!ccgw->src_idx && !ccgw->dst_idx) 734 if (!ccgw->src_idx && !ccgw->dst_idx)