ncsi-netlink.c (30aa69e7bd9f7af3574120249eecb3726dcaf737) | ncsi-netlink.c (9771b8ccdfa6dcb1ac5128ca7fe8649f3092d392) |
---|---|
1/* 2 * Copyright Samuel Mendoza-Jonas, IBM Corporation 2018. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 */ 9 10#include <linux/module.h> 11#include <linux/kernel.h> 12#include <linux/if_arp.h> 13#include <linux/rtnetlink.h> 14#include <linux/etherdevice.h> | 1/* 2 * Copyright Samuel Mendoza-Jonas, IBM Corporation 2018. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 */ 9 10#include <linux/module.h> 11#include <linux/kernel.h> 12#include <linux/if_arp.h> 13#include <linux/rtnetlink.h> 14#include <linux/etherdevice.h> |
15#include <linux/module.h> | |
16#include <net/genetlink.h> 17#include <net/ncsi.h> 18#include <linux/skbuff.h> 19#include <net/sock.h> 20#include <uapi/linux/ncsi.h> 21 22#include "internal.h" | 15#include <net/genetlink.h> 16#include <net/ncsi.h> 17#include <linux/skbuff.h> 18#include <net/sock.h> 19#include <uapi/linux/ncsi.h> 20 21#include "internal.h" |
22#include "ncsi-pkt.h" |
|
23#include "ncsi-netlink.h" 24 25static struct genl_family ncsi_genl_family; 26 27static const struct nla_policy ncsi_genl_policy[NCSI_ATTR_MAX + 1] = { 28 [NCSI_ATTR_IFINDEX] = { .type = NLA_U32 }, 29 [NCSI_ATTR_PACKAGE_LIST] = { .type = NLA_NESTED }, 30 [NCSI_ATTR_PACKAGE_ID] = { .type = NLA_U32 }, 31 [NCSI_ATTR_CHANNEL_ID] = { .type = NLA_U32 }, | 23#include "ncsi-netlink.h" 24 25static struct genl_family ncsi_genl_family; 26 27static const struct nla_policy ncsi_genl_policy[NCSI_ATTR_MAX + 1] = { 28 [NCSI_ATTR_IFINDEX] = { .type = NLA_U32 }, 29 [NCSI_ATTR_PACKAGE_LIST] = { .type = NLA_NESTED }, 30 [NCSI_ATTR_PACKAGE_ID] = { .type = NLA_U32 }, 31 [NCSI_ATTR_CHANNEL_ID] = { .type = NLA_U32 }, |
32 [NCSI_ATTR_DATA] = { .type = NLA_BINARY, .len = 2048 }, |
|
32}; 33 34static struct ncsi_dev_priv *ndp_from_ifindex(struct net *net, u32 ifindex) 35{ 36 struct ncsi_dev_priv *ndp; 37 struct net_device *dev; 38 struct ncsi_dev *nd; 39 struct ncsi_dev; --- 321 unchanged lines hidden (view full) --- 361 362 /* Bounce the NCSI channel to set changes */ 363 ncsi_stop_dev(&ndp->ndev); 364 ncsi_start_dev(&ndp->ndev); 365 366 return 0; 367} 368 | 33}; 34 35static struct ncsi_dev_priv *ndp_from_ifindex(struct net *net, u32 ifindex) 36{ 37 struct ncsi_dev_priv *ndp; 38 struct net_device *dev; 39 struct ncsi_dev *nd; 40 struct ncsi_dev; --- 321 unchanged lines hidden (view full) --- 362 363 /* Bounce the NCSI channel to set changes */ 364 ncsi_stop_dev(&ndp->ndev); 365 ncsi_start_dev(&ndp->ndev); 366 367 return 0; 368} 369 |
370static int ncsi_send_cmd_nl(struct sk_buff *msg, struct genl_info *info) 371{ 372 struct ncsi_dev_priv *ndp; 373 struct ncsi_pkt_hdr *hdr; 374 struct ncsi_cmd_arg nca; 375 unsigned char *data; 376 u32 package_id; 377 u32 channel_id; 378 int len, ret; 379 380 if (!info || !info->attrs) { 381 ret = -EINVAL; 382 goto out; 383 } 384 385 if (!info->attrs[NCSI_ATTR_IFINDEX]) { 386 ret = -EINVAL; 387 goto out; 388 } 389 390 if (!info->attrs[NCSI_ATTR_PACKAGE_ID]) { 391 ret = -EINVAL; 392 goto out; 393 } 394 395 if (!info->attrs[NCSI_ATTR_CHANNEL_ID]) { 396 ret = -EINVAL; 397 goto out; 398 } 399 400 if (!info->attrs[NCSI_ATTR_DATA]) { 401 ret = -EINVAL; 402 goto out; 403 } 404 405 ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)), 406 nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX])); 407 if (!ndp) { 408 ret = -ENODEV; 409 goto out; 410 } 411 412 package_id = nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_ID]); 413 channel_id = nla_get_u32(info->attrs[NCSI_ATTR_CHANNEL_ID]); 414 415 if (package_id >= NCSI_MAX_PACKAGE || channel_id >= NCSI_MAX_CHANNEL) { 416 ret = -ERANGE; 417 goto out_netlink; 418 } 419 420 len = nla_len(info->attrs[NCSI_ATTR_DATA]); 421 if (len < sizeof(struct ncsi_pkt_hdr)) { 422 netdev_info(ndp->ndev.dev, "NCSI: no command to send %u\n", 423 package_id); 424 ret = -EINVAL; 425 goto out_netlink; 426 } else { 427 data = (unsigned char *)nla_data(info->attrs[NCSI_ATTR_DATA]); 428 } 429 430 hdr = (struct ncsi_pkt_hdr *)data; 431 432 nca.ndp = ndp; 433 nca.package = (unsigned char)package_id; 434 nca.channel = (unsigned char)channel_id; 435 nca.type = hdr->type; 436 nca.req_flags = NCSI_REQ_FLAG_NETLINK_DRIVEN; 437 nca.info = info; 438 nca.payload = ntohs(hdr->length); 439 nca.data = data + sizeof(*hdr); 440 441 ret = ncsi_xmit_cmd(&nca); 442out_netlink: 443 if (ret != 0) { 444 netdev_err(ndp->ndev.dev, 445 "NCSI: Error %d sending command\n", 446 ret); 447 ncsi_send_netlink_err(ndp->ndev.dev, 448 info->snd_seq, 449 info->snd_portid, 450 info->nlhdr, 451 ret); 452 } 453out: 454 return ret; 455} 456 457int ncsi_send_netlink_rsp(struct ncsi_request *nr, 458 struct ncsi_package *np, 459 struct ncsi_channel *nc) 460{ 461 struct sk_buff *skb; 462 struct net *net; 463 void *hdr; 464 int rc; 465 466 net = dev_net(nr->rsp->dev); 467 468 skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 469 if (!skb) 470 return -ENOMEM; 471 472 hdr = genlmsg_put(skb, nr->snd_portid, nr->snd_seq, 473 &ncsi_genl_family, 0, NCSI_CMD_SEND_CMD); 474 if (!hdr) { 475 kfree_skb(skb); 476 return -EMSGSIZE; 477 } 478 479 nla_put_u32(skb, NCSI_ATTR_IFINDEX, nr->rsp->dev->ifindex); 480 if (np) 481 nla_put_u32(skb, NCSI_ATTR_PACKAGE_ID, np->id); 482 if (nc) 483 nla_put_u32(skb, NCSI_ATTR_CHANNEL_ID, nc->id); 484 else 485 nla_put_u32(skb, NCSI_ATTR_CHANNEL_ID, NCSI_RESERVED_CHANNEL); 486 487 rc = nla_put(skb, NCSI_ATTR_DATA, nr->rsp->len, (void *)nr->rsp->data); 488 if (rc) 489 goto err; 490 491 genlmsg_end(skb, hdr); 492 return genlmsg_unicast(net, skb, nr->snd_portid); 493 494err: 495 kfree_skb(skb); 496 return rc; 497} 498 499int ncsi_send_netlink_timeout(struct ncsi_request *nr, 500 struct ncsi_package *np, 501 struct ncsi_channel *nc) 502{ 503 struct sk_buff *skb; 504 struct net *net; 505 void *hdr; 506 507 skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 508 if (!skb) 509 return -ENOMEM; 510 511 hdr = genlmsg_put(skb, nr->snd_portid, nr->snd_seq, 512 &ncsi_genl_family, 0, NCSI_CMD_SEND_CMD); 513 if (!hdr) { 514 kfree_skb(skb); 515 return -EMSGSIZE; 516 } 517 518 net = dev_net(nr->cmd->dev); 519 520 nla_put_u32(skb, NCSI_ATTR_IFINDEX, nr->cmd->dev->ifindex); 521 522 if (np) 523 nla_put_u32(skb, NCSI_ATTR_PACKAGE_ID, np->id); 524 else 525 nla_put_u32(skb, NCSI_ATTR_PACKAGE_ID, 526 NCSI_PACKAGE_INDEX((((struct ncsi_pkt_hdr *) 527 nr->cmd->data)->channel))); 528 529 if (nc) 530 nla_put_u32(skb, NCSI_ATTR_CHANNEL_ID, nc->id); 531 else 532 nla_put_u32(skb, NCSI_ATTR_CHANNEL_ID, NCSI_RESERVED_CHANNEL); 533 534 genlmsg_end(skb, hdr); 535 return genlmsg_unicast(net, skb, nr->snd_portid); 536} 537 538int ncsi_send_netlink_err(struct net_device *dev, 539 u32 snd_seq, 540 u32 snd_portid, 541 struct nlmsghdr *nlhdr, 542 int err) 543{ 544 struct nlmsghdr *nlh; 545 struct nlmsgerr *nle; 546 struct sk_buff *skb; 547 struct net *net; 548 549 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 550 if (!skb) 551 return -ENOMEM; 552 553 net = dev_net(dev); 554 555 nlh = nlmsg_put(skb, snd_portid, snd_seq, 556 NLMSG_ERROR, sizeof(*nle), 0); 557 nle = (struct nlmsgerr *)nlmsg_data(nlh); 558 nle->error = err; 559 memcpy(&nle->msg, nlhdr, sizeof(*nlh)); 560 561 nlmsg_end(skb, nlh); 562 563 return nlmsg_unicast(net->genl_sock, skb, snd_portid); 564} 565 |
|
369static const struct genl_ops ncsi_ops[] = { 370 { 371 .cmd = NCSI_CMD_PKG_INFO, 372 .policy = ncsi_genl_policy, 373 .doit = ncsi_pkg_info_nl, 374 .dumpit = ncsi_pkg_info_all_nl, 375 .flags = 0, 376 }, --- 4 unchanged lines hidden (view full) --- 381 .flags = GENL_ADMIN_PERM, 382 }, 383 { 384 .cmd = NCSI_CMD_CLEAR_INTERFACE, 385 .policy = ncsi_genl_policy, 386 .doit = ncsi_clear_interface_nl, 387 .flags = GENL_ADMIN_PERM, 388 }, | 566static const struct genl_ops ncsi_ops[] = { 567 { 568 .cmd = NCSI_CMD_PKG_INFO, 569 .policy = ncsi_genl_policy, 570 .doit = ncsi_pkg_info_nl, 571 .dumpit = ncsi_pkg_info_all_nl, 572 .flags = 0, 573 }, --- 4 unchanged lines hidden (view full) --- 578 .flags = GENL_ADMIN_PERM, 579 }, 580 { 581 .cmd = NCSI_CMD_CLEAR_INTERFACE, 582 .policy = ncsi_genl_policy, 583 .doit = ncsi_clear_interface_nl, 584 .flags = GENL_ADMIN_PERM, 585 }, |
586 { 587 .cmd = NCSI_CMD_SEND_CMD, 588 .policy = ncsi_genl_policy, 589 .doit = ncsi_send_cmd_nl, 590 .flags = GENL_ADMIN_PERM, 591 }, |
|
389}; 390 391static struct genl_family ncsi_genl_family __ro_after_init = { 392 .name = "NCSI", 393 .version = 0, 394 .maxattr = NCSI_ATTR_MAX, 395 .module = THIS_MODULE, 396 .ops = ncsi_ops, --- 24 unchanged lines hidden --- | 592}; 593 594static struct genl_family ncsi_genl_family __ro_after_init = { 595 .name = "NCSI", 596 .version = 0, 597 .maxattr = NCSI_ATTR_MAX, 598 .module = THIS_MODULE, 599 .ops = ncsi_ops, --- 24 unchanged lines hidden --- |