static int ncsi_validate_rsp_pkt(struct ncsi_request *nr, unsigned short payload) { struct ncsi_rsp_pkt_hdr *h; u32 checksum; __be32 *pchecksum; /* Check NCSI packet header. We don't need validate * the packet type, which should have been checked * before calling this function. */ h = (struct ncsi_rsp_pkt_hdr *)skb_network_header(nr->rsp); if (h->common.revision != NCSI_PKT_REVISION) { netdev_dbg(nr->ndp->ndev.dev, "NCSI: unsupported header revision\n"); return -EINVAL; } if (ntohs(h->common.length) != payload) { netdev_dbg(nr->ndp->ndev.dev, "NCSI: payload length mismatched\n"); return -EINVAL; } /* Check on code and reason */ if (ntohs(h->code) != NCSI_PKT_RSP_C_COMPLETED || ntohs(h->reason) != NCSI_PKT_RSP_R_NO_ERROR) { netdev_dbg(nr->ndp->ndev.dev, "NCSI: non zero response/reason code\n"); return -EPERM; } /* Validate checksum, which might be zeroes if the * sender doesn't support checksum according to NCSI * specification. */ pchecksum = (__be32 *)((void *)(h + 1) + payload - 4); if (ntohl(*pchecksum) == 0) return 0; checksum = ncsi_calculate_checksum((unsigned char *)h, sizeof(*h) + payload - 4); if (*pchecksum != htonl(checksum)) { netdev_dbg(nr->ndp->ndev.dev, "NCSI: checksum mismatched\n"); return -EINVAL; } return 0; }
/* This function should be called after the data area has been * populated completely. */ static void ncsi_cmd_build_header(struct ncsi_pkt_hdr *h, struct ncsi_cmd_arg *nca) { u32 checksum; __be32 *pchecksum; h->mc_id = 0; h->revision = NCSI_PKT_REVISION; h->reserved = 0; h->id = nca->id; h->type = nca->type; h->channel = NCSI_TO_CHANNEL(nca->package, nca->channel); h->length = htons(nca->payload); h->reserved1[0] = 0; h->reserved1[1] = 0; /* Fill with calculated checksum */ checksum = ncsi_calculate_checksum((unsigned char *)h, sizeof(*h) + nca->payload); pchecksum = (__be32 *)((void *)h + sizeof(struct ncsi_pkt_hdr) + nca->payload); *pchecksum = htonl(checksum); }