ncsi-rsp.c (188de5dd80b2b7986e75821374efb67081049b6e) ncsi-rsp.c (9771b8ccdfa6dcb1ac5128ca7fe8649f3092d392)
1/*
2 * Copyright Gavin Shan, IBM Corporation 2016.
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/init.h>
13#include <linux/netdevice.h>
14#include <linux/skbuff.h>
15
16#include <net/ncsi.h>
17#include <net/net_namespace.h>
18#include <net/sock.h>
1/*
2 * Copyright Gavin Shan, IBM Corporation 2016.
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/init.h>
13#include <linux/netdevice.h>
14#include <linux/skbuff.h>
15
16#include <net/ncsi.h>
17#include <net/net_namespace.h>
18#include <net/sock.h>
19#include <net/genetlink.h>
19
20#include "internal.h"
21#include "ncsi-pkt.h"
20
21#include "internal.h"
22#include "ncsi-pkt.h"
23#include "ncsi-netlink.h"
22
23static int ncsi_validate_rsp_pkt(struct ncsi_request *nr,
24 unsigned short payload)
25{
26 struct ncsi_rsp_pkt_hdr *h;
27 u32 checksum;
28 __be32 *pchecksum;
29
30 /* Check NCSI packet header. We don't need validate
31 * the packet type, which should have been checked
32 * before calling this function.
33 */
34 h = (struct ncsi_rsp_pkt_hdr *)skb_network_header(nr->rsp);
24
25static int ncsi_validate_rsp_pkt(struct ncsi_request *nr,
26 unsigned short payload)
27{
28 struct ncsi_rsp_pkt_hdr *h;
29 u32 checksum;
30 __be32 *pchecksum;
31
32 /* Check NCSI packet header. We don't need validate
33 * the packet type, which should have been checked
34 * before calling this function.
35 */
36 h = (struct ncsi_rsp_pkt_hdr *)skb_network_header(nr->rsp);
35 if (h->common.revision != NCSI_PKT_REVISION)
37
38 if (h->common.revision != NCSI_PKT_REVISION) {
39 netdev_dbg(nr->ndp->ndev.dev,
40 "NCSI: unsupported header revision\n");
36 return -EINVAL;
41 return -EINVAL;
37 if (ntohs(h->common.length) != payload)
42 }
43 if (ntohs(h->common.length) != payload) {
44 netdev_dbg(nr->ndp->ndev.dev,
45 "NCSI: payload length mismatched\n");
38 return -EINVAL;
46 return -EINVAL;
47 }
39
40 /* Check on code and reason */
41 if (ntohs(h->code) != NCSI_PKT_RSP_C_COMPLETED ||
48
49 /* Check on code and reason */
50 if (ntohs(h->code) != NCSI_PKT_RSP_C_COMPLETED ||
42 ntohs(h->reason) != NCSI_PKT_RSP_R_NO_ERROR)
43 return -EINVAL;
51 ntohs(h->reason) != NCSI_PKT_RSP_R_NO_ERROR) {
52 netdev_dbg(nr->ndp->ndev.dev,
53 "NCSI: non zero response/reason code\n");
54 return -EPERM;
55 }
44
45 /* Validate checksum, which might be zeroes if the
46 * sender doesn't support checksum according to NCSI
47 * specification.
48 */
49 pchecksum = (__be32 *)((void *)(h + 1) + payload - 4);
50 if (ntohl(*pchecksum) == 0)
51 return 0;
52
53 checksum = ncsi_calculate_checksum((unsigned char *)h,
54 sizeof(*h) + payload - 4);
56
57 /* Validate checksum, which might be zeroes if the
58 * sender doesn't support checksum according to NCSI
59 * specification.
60 */
61 pchecksum = (__be32 *)((void *)(h + 1) + payload - 4);
62 if (ntohl(*pchecksum) == 0)
63 return 0;
64
65 checksum = ncsi_calculate_checksum((unsigned char *)h,
66 sizeof(*h) + payload - 4);
55 if (*pchecksum != htonl(checksum))
67
68 if (*pchecksum != htonl(checksum)) {
69 netdev_dbg(nr->ndp->ndev.dev, "NCSI: checksum mismatched\n");
56 return -EINVAL;
70 return -EINVAL;
71 }
57
58 return 0;
59}
60
61static int ncsi_rsp_handler_cis(struct ncsi_request *nr)
62{
63 struct ncsi_rsp_pkt *rsp;
64 struct ncsi_dev_priv *ndp = nr->ndp;

--- 871 unchanged lines hidden (view full) ---

936 if (!np)
937 return -ENODEV;
938
939 memcpy(np->uuid, rsp->uuid, sizeof(rsp->uuid));
940
941 return 0;
942}
943
72
73 return 0;
74}
75
76static int ncsi_rsp_handler_cis(struct ncsi_request *nr)
77{
78 struct ncsi_rsp_pkt *rsp;
79 struct ncsi_dev_priv *ndp = nr->ndp;

--- 871 unchanged lines hidden (view full) ---

951 if (!np)
952 return -ENODEV;
953
954 memcpy(np->uuid, rsp->uuid, sizeof(rsp->uuid));
955
956 return 0;
957}
958
959static int ncsi_rsp_handler_netlink(struct ncsi_request *nr)
960{
961 struct ncsi_dev_priv *ndp = nr->ndp;
962 struct ncsi_rsp_pkt *rsp;
963 struct ncsi_package *np;
964 struct ncsi_channel *nc;
965 int ret;
966
967 /* Find the package */
968 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
969 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
970 &np, &nc);
971 if (!np)
972 return -ENODEV;
973
974 ret = ncsi_send_netlink_rsp(nr, np, nc);
975
976 return ret;
977}
978
944static struct ncsi_rsp_handler {
945 unsigned char type;
946 int payload;
947 int (*handler)(struct ncsi_request *nr);
948} ncsi_rsp_handlers[] = {
949 { NCSI_PKT_RSP_CIS, 4, ncsi_rsp_handler_cis },
950 { NCSI_PKT_RSP_SP, 4, ncsi_rsp_handler_sp },
951 { NCSI_PKT_RSP_DP, 4, ncsi_rsp_handler_dp },

--- 86 unchanged lines hidden (view full) ---

1038 payload = nrh->payload;
1039 if (payload < 0)
1040 payload = ntohs(hdr->length);
1041 ret = ncsi_validate_rsp_pkt(nr, payload);
1042 if (ret) {
1043 netdev_warn(ndp->ndev.dev,
1044 "NCSI: 'bad' packet ignored for type 0x%x\n",
1045 hdr->type);
979static struct ncsi_rsp_handler {
980 unsigned char type;
981 int payload;
982 int (*handler)(struct ncsi_request *nr);
983} ncsi_rsp_handlers[] = {
984 { NCSI_PKT_RSP_CIS, 4, ncsi_rsp_handler_cis },
985 { NCSI_PKT_RSP_SP, 4, ncsi_rsp_handler_sp },
986 { NCSI_PKT_RSP_DP, 4, ncsi_rsp_handler_dp },

--- 86 unchanged lines hidden (view full) ---

1073 payload = nrh->payload;
1074 if (payload < 0)
1075 payload = ntohs(hdr->length);
1076 ret = ncsi_validate_rsp_pkt(nr, payload);
1077 if (ret) {
1078 netdev_warn(ndp->ndev.dev,
1079 "NCSI: 'bad' packet ignored for type 0x%x\n",
1080 hdr->type);
1081
1082 if (nr->flags == NCSI_REQ_FLAG_NETLINK_DRIVEN) {
1083 if (ret == -EPERM)
1084 goto out_netlink;
1085 else
1086 ncsi_send_netlink_err(ndp->ndev.dev,
1087 nr->snd_seq,
1088 nr->snd_portid,
1089 &nr->nlhdr,
1090 ret);
1091 }
1046 goto out;
1047 }
1048
1049 /* Process the packet */
1050 ret = nrh->handler(nr);
1051 if (ret)
1052 netdev_err(ndp->ndev.dev,
1053 "NCSI: Handler for packet type 0x%x returned %d\n",
1054 hdr->type, ret);
1092 goto out;
1093 }
1094
1095 /* Process the packet */
1096 ret = nrh->handler(nr);
1097 if (ret)
1098 netdev_err(ndp->ndev.dev,
1099 "NCSI: Handler for packet type 0x%x returned %d\n",
1100 hdr->type, ret);
1101
1102out_netlink:
1103 if (nr->flags == NCSI_REQ_FLAG_NETLINK_DRIVEN) {
1104 ret = ncsi_rsp_handler_netlink(nr);
1105 if (ret) {
1106 netdev_err(ndp->ndev.dev,
1107 "NCSI: Netlink handler for packet type 0x%x returned %d\n",
1108 hdr->type, ret);
1109 }
1110 }
1111
1055out:
1056 ncsi_free_request(nr);
1057 return ret;
1058}
1112out:
1113 ncsi_free_request(nr);
1114 return ret;
1115}