From e0fcd4809efb3210136f77d87f2846ed37381c7f Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Fri, 29 May 2026 14:35:33 +0200 Subject: [PATCH] nwbind: implement additional broadcast message calls Add the missing NCP 21 message service endpoints for disabling/enabling broadcast reception and for the newer send/get broadcast message calls. Track a per-connection broadcast_disabled flag and use a shared helper for storing pending broadcast messages and notifying the target nwconn process. The old NCP 21/00 send path now uses the same helper as the newer NCP 21/10 path. Also improve UNKNOWN FUNCTION logging in nwconn.c by including the NCP type, function and, where available, subfunction. This makes future missing-endpoint logs easier to map back to SDK/NCP documentation. Based on the existing MARS-NWE message handling, the old lwared broadcast implementation, and the Novell WebSDK message service layouts. --- include/nwbind.h | 1 + src/nwbind.c | 81 +++++++++++++++++++++++++++++++++++++++--------- src/nwconn.c | 18 +++++++++-- 3 files changed, 82 insertions(+), 18 deletions(-) diff --git a/include/nwbind.h b/include/nwbind.h index 176c284..ba0e059 100644 --- a/include/nwbind.h +++ b/include/nwbind.h @@ -37,6 +37,7 @@ typedef struct { uint8 crypt_key[8]; /* password generation */ time_t t_login; /* login time */ uint8 message[60]; /* saved BCastmessage */ + int broadcast_disabled; /* client refuses messages */ int active; /* 0=closed, 1= active */ int send_to_sock; /* this is the receiving sock */ int pid_nwconn; /* pid of user process nwconn */ diff --git a/src/nwbind.c b/src/nwbind.c index 540c75d..109ef2d 100644 --- a/src/nwbind.c +++ b/src/nwbind.c @@ -426,6 +426,7 @@ static void open_clear_connection(int conn, int activate, uint8 *addr) CONNECTION *c = &connections[conn]; c->active = activate; c->message[0] = '\0'; + c->broadcast_disabled = 0; c->t_login = 0; if (activate && addr) { @@ -496,6 +497,38 @@ static int build_login_response(uint8 *responsedata, uint32 obj_id) return(result); } + +/* + * ncp21_store_broadcast_message + * + * Store a pending broadcast message for one target connection and notify the + * corresponding nwconn process. The helper returns the old NCP 21/00 status + * byte by default and the newer NCP 21/10 status byte when new_status is set. + */ +static uint8 ncp21_store_broadcast_message(int connr, uint8 *msg, + int msglen, int new_status) +{ + uint8 result = new_status ? 0x01 : 0xff; /* illegal/bad station */ + CONNECTION *cn; + + if (connr <= 0 || --connr >= max_connections) + return(result); + + cn = &connections[connr]; + if (!cn->active) + return(new_status ? 0x02 : 0xff); /* not logged/target bad */ + + if (cn->broadcast_disabled) + return(new_status ? 0x03 : 0xff); /* not accepting messages */ + + if (cn->message[0]) + return(new_status ? 0x04 : 0xfc); /* already holds message */ + + strmaxcpy(cn->message, msg, min(58, msglen)); + nwserv_handle_msg(connr+1); + return(0); +} + static void handle_fxx(int gelen, int func) { IPX_DATA ipxoutdata; @@ -553,18 +586,10 @@ static void handle_fxx(int gelen, int func) *p++ = (uint8) count_conns; while (++k < count_conns) { int connr = (int) (*conns++); - int result = 0xff; /* target not ok */ - CONNECTION *cn; - if (connr > 0 && --connr < max_connections - && ((cn = &connections[connr]))->active ) { - if (!cn->message[0]) { - strmaxcpy(cn->message, msg, min(58, msglen)); - result = 0; /* Ok */ - } else result = 0xfc; /* server holds message */ - nwserv_handle_msg(connr+1); + uint8 result = ncp21_store_broadcast_message(connr, msg, msglen, 0); + if (!result) one_found++; - } - *p++ = (uint8)result; + *p++ = result; } if (one_found) data_len = count_conns+1; else completition=0xff; @@ -578,9 +603,13 @@ static void handle_fxx(int gelen, int func) } break; + case 0x02: { /* Disable Broadcasts */ + act_c->broadcast_disabled = 1; + } + break; + case 0x03: { /* Enable Broadcasts */ - ;;; - XDPRINTF((2, 0, "TODO: enable Broadcasts")); + act_c->broadcast_disabled = 0; } break; @@ -591,8 +620,30 @@ static void handle_fxx(int gelen, int func) } break; - case 0xa: /* Send Broadcast Message (new) */ - case 0xb: /* Get Broadcast Message (new) */ + case 0x0a: { /* Send Broadcast Message (new) */ + int count_conns = GET_BE16(rdata); + uint8 *conns = rdata+2; + int msglen = *(conns + count_conns*2); + uint8 *msg = conns + count_conns*2 + 1; + uint8 *p = responsedata; + int k; + U16_TO_BE16(count_conns, p); + p += 2; + for (k = 0; k < count_conns; k++) { + int connr = GET_BE16(conns + k*2); + *p++ = ncp21_store_broadcast_message(connr, msg, msglen, 1); + } + data_len = count_conns + 2; + } + break; + + case 0x0b: { /* Get Broadcast Message (new) */ + *responsedata = (uint8) strmaxcpy(responsedata+1, act_c->message, 58); + act_c->message[0] = '\0'; + data_len = (int)(*responsedata) + 1; + } + break; + default : completition=0xfb; /* not handled */ } /* switch */ } else if (0x16 == func) { diff --git a/src/nwconn.c b/src/nwconn.c index 92403b5..f5d21e8 100644 --- a/src/nwconn.c +++ b/src/nwconn.c @@ -2624,9 +2624,21 @@ static int handle_ncp_serv(void) if (nw_debug && (completition == 0xfb || (do_druck == 1))) { /* UNKWON FUNCTION od. TYPE */ pr_debug_request(); - if (completition == 0xfb) - XDPRINTF((0,0, "UNKNOWN FUNCTION or TYPE: 0x%x", function)); - else if (data_len){ + if (completition == 0xfb) { + int req_len = requestlen - sizeof(NCPREQUEST); + int subfunc = -1; + if (req_len > 2 && (function == 0x15 || function == 0x16 || function == 0x17)) + subfunc = requestdata[2]; + else if (req_len > 0 && function == 0x20) + subfunc = requestdata[0]; + + if (subfunc > -1) + XDPRINTF((0,0, "UNKNOWN FUNCTION or TYPE: type=0x%x func=0x%x ufunc=0x%x", + ncp_type, function, subfunc)); + else + XDPRINTF((0,0, "UNKNOWN FUNCTION or TYPE: type=0x%x func=0x%x", + ncp_type, function)); + } else if (data_len){ int j = data_len; uint8 *p = responsedata; XDPRINTF((0,2, "RSPONSE: len %d, DATA:", data_len));