diff --git a/lib/cwmp.ts b/lib/cwmp.ts
index 1bece60..9b0fc8e 100644
--- a/lib/cwmp.ts
+++ b/lib/cwmp.ts
@@ -45,6 +45,7 @@ import {
InformRequest,
Preset,
GetRPCMethodsResponse,
+ CpeFault,
} from "./types";
import { IncomingMessage, ServerResponse } from "http";
import { Readable } from "stream";
@@ -1256,6 +1257,41 @@ async function processRequest(
session.clearProvisions(sessionContext);
}
return nextRpc(sessionContext);
+ } else if (rpc.unknownMethod) {
+ if (sessionContext.state === 1) {
+ logger.accessWarn({
+ sessionContext: sessionContext,
+ message: "Method not supported",
+ method: rpc.unknownMethod,
+ });
+
+ const f: CpeFault = {
+ faultCode: "Server",
+ faultString: "CWMP fault",
+ detail: {
+ faultCode: "8000",
+ faultString: "Method not supported",
+ },
+ };
+
+ const res = soap.response({
+ id: rpc.id,
+ acsFault: f,
+ cwmpVersion: sessionContext.cwmpVersion,
+ });
+
+ return writeResponse(sessionContext, res);
+ } else if (sessionContext.state === 2) {
+ const fault = {
+ code: "invalid_response",
+ message: "Response name does not match request name",
+ };
+ recordFault(sessionContext, fault);
+ session.clearProvisions(sessionContext);
+ return nextRpc(sessionContext);
+ } else {
+ return reportBadState(sessionContext);
+ }
} else {
// CPE sent empty response
if (sessionContext.state !== 1) return reportBadState(sessionContext);
diff --git a/lib/soap.ts b/lib/soap.ts
index 9a8cbbd..7894dc1 100644
--- a/lib/soap.ts
+++ b/lib/soap.ts
@@ -730,6 +730,18 @@ function RequestDownloadResponse(): string {
return "";
}
+function AcsFault(f: CpeFault): string {
+ return `${encodeEntities(
+ f.faultCode
+ )}${encodeEntities(
+ f.faultString
+ )}${encodeEntities(
+ f.detail.faultCode
+ )}${encodeEntities(
+ f.detail.faultString
+ )}`;
+}
+
function faultStruct(xml: Element): FaultStruct {
let faultCode: string,
faultString: string,
@@ -838,6 +850,7 @@ export function request(
cpeRequest: null,
cpeFault: null,
cpeResponse: null,
+ unknownMethod: null,
};
if (!body.length) return rpc;
@@ -959,7 +972,8 @@ export function request(
rpc.cpeFault = fault(methodElement);
break;
default:
- throw new Error(`8000 Method not supported ${methodElement.localName}`);
+ rpc.unknownMethod = methodElement.localName;
+ break;
}
return rpc;
@@ -987,6 +1001,7 @@ export function response(rpc: {
id: string;
acsRequest?: AcsRequest;
acsResponse?: AcsResponse;
+ acsFault?: CpeFault;
cwmpVersion?: string;
}): { code: number; headers: Record; data: string } {
const headers = {
@@ -1055,6 +1070,8 @@ export function response(rpc: {
`Unknown method request ${(rpc.acsRequest as AcsRequest).name}`
);
}
+ } else if (rpc.acsFault) {
+ body = AcsFault(rpc.acsFault);
}
headers["Content-Type"] = 'text/xml; charset="utf-8"';
diff --git a/lib/types.ts b/lib/types.ts
index 1f41836..90b2c84 100644
--- a/lib/types.ts
+++ b/lib/types.ts
@@ -526,6 +526,7 @@ export interface SoapMessage {
cpeRequest?: CpeRequest;
cpeFault?: CpeFault;
cpeResponse?: CpeResponse;
+ unknownMethod?: string;
}
export interface ScriptResult {