nwbind: implement additional broadcast message calls
All checks were successful
Source release / source-package (push) Successful in 50s

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.
This commit is contained in:
Mario Fetka
2026-05-29 14:35:33 +02:00
parent 4c28bdd3cd
commit e0fcd4809e
3 changed files with 82 additions and 18 deletions

View File

@@ -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 */

View File

@@ -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) {

View File

@@ -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));