Skip to content

Commit fd555ce

Browse files
committed
Implemented IPX_RECEIVE_BROADCAST option, updated router/rclient API and added proper checks when receiving broadcast packets to the router main loop.
1 parent 646ab3b commit fd555ce

File tree

5 files changed

+65
-49
lines changed

5 files changed

+65
-49
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,5 @@ src/dpwsockx_stubs.s: src/dpwsockx_stubs.txt
8585
src/%_stubs.o: src/%_stubs.s
8686
nasm -f win32 -o $@ $<
8787

88-
src/%.o: src/%.c src/ipxwrapper.h src/config.h src/common.h
88+
src/%.o: src/%.c src/ipxwrapper.h src/config.h src/common.h src/router.h
8989
$(CC) $(CFLAGS) -c -o $@ $<

src/ipxwrapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#define IPX_RECV (int)(1<<4)
3939
#define IPX_REUSE (int)(1<<6)
4040
#define IPX_CONNECTED (int)(1<<7)
41+
#define IPX_RECV_BCAST (int)(1<<8)
4142

4243
#define RETURN(...) \
4344
unlock_sockets();\

src/router.c

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,8 @@ DWORD router_main(void *arg) {
287287
if(
288288
ra->local_port &&
289289
(ra->filter_ptype < 0 || ra->filter_ptype == packet->ptype) &&
290-
(memcmp(packet->dest_net, ra->addr.sa_netnum, 4) == 0 || memcmp(packet->dest_net, f6, 4) == 0) &&
291-
(memcmp(packet->dest_node, ra->addr.sa_nodenum, 6) == 0 || memcmp(packet->dest_node, f6, 6) == 0) &&
290+
(memcmp(packet->dest_net, ra->addr.sa_netnum, 4) == 0 || (memcmp(packet->dest_net, f6, 4) == 0 && (ra->flags & IPX_BROADCAST || !global_conf.w95_bug) && ra->flags & IPX_RECV_BCAST)) &&
291+
(memcmp(packet->dest_node, ra->addr.sa_nodenum, 6) == 0 || (memcmp(packet->dest_node, f6, 6) == 0 && (ra->flags & IPX_BROADCAST || !global_conf.w95_bug) && ra->flags & IPX_RECV_BCAST)) &&
292292
packet->dest_socket == ra->addr.sa_socket &&
293293

294294
/* Check source IP is within correct subnet */
@@ -314,7 +314,7 @@ DWORD router_main(void *arg) {
314314
return 0;
315315
}
316316

317-
static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, BOOL reuse) {
317+
static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, int flags) {
318318
/* Network number 00:00:00:00 is specified as the "current" network, this code
319319
* treats it as a wildcard when used for the network OR node numbers.
320320
*
@@ -406,7 +406,7 @@ static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock,
406406
struct router_addr *a = router->addrs;
407407

408408
while(a) {
409-
if(a->addr.sa_socket == addr->sa_socket && (!a->reuse || !reuse)) {
409+
if(a->addr.sa_socket == addr->sa_socket && (!(a->flags & IPX_REUSE) || !(flags & IPX_REUSE))) {
410410
log_printf("bind failed: requested socket in use");
411411

412412
LeaveCriticalSection(&(router->crit_sec));
@@ -433,7 +433,7 @@ static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock,
433433
new_addr->ws_socket = sock;
434434
new_addr->control_socket = control;
435435
new_addr->filter_ptype = -1;
436-
new_addr->reuse = reuse;
436+
new_addr->flags = flags;
437437
new_addr->ipaddr = iface_ipaddr;
438438
new_addr->netmask = iface_netmask;
439439
new_addr->next = router->addrs;
@@ -512,28 +512,30 @@ static void router_set_filter(struct router_vars *router, SOCKET control, SOCKET
512512
LeaveCriticalSection(&(router->crit_sec));
513513
}
514514

515-
static int router_set_reuse(struct router_vars *router, SOCKET control, SOCKET sock, BOOL reuse) {
515+
static int router_set_flags(struct router_vars *router, SOCKET control, SOCKET sock, int flags) {
516516
EnterCriticalSection(&(router->crit_sec));
517517

518518
struct router_addr *addr = router_get(router, control, sock);
519519
if(addr) {
520-
struct router_addr *test = router->addrs;
521-
522-
while(test) {
523-
if(addr != test && memcmp(&(addr->addr), &(test->addr), sizeof(struct sockaddr_ipx)) == 0 && !reuse) {
524-
/* Refuse to disable SO_REUSEADDR when another binding for the same address exists */
525-
LeaveCriticalSection(&(router->crit_sec));
526-
return 0;
527-
}
520+
if(addr->flags & IPX_REUSE && !(flags & IPX_REUSE)) {
521+
struct router_addr *test = router->addrs;
528522

529-
test = test->next;
523+
while(test) {
524+
if(addr != test && memcmp(&(addr->addr), &(test->addr), sizeof(struct sockaddr_ipx)) == 0) {
525+
/* Refuse to disable SO_REUSEADDR when another binding for the same address exists */
526+
LeaveCriticalSection(&(router->crit_sec));
527+
return WSAEINVAL;
528+
}
529+
530+
test = test->next;
531+
}
530532
}
531533

532-
addr->reuse = reuse;
534+
addr->flags = flags;
533535
}
534536

535537
LeaveCriticalSection(&(router->crit_sec));
536-
return 1;
538+
return ERROR_SUCCESS;
537539
}
538540

539541
static BOOL router_set_remote(struct router_vars *router, SOCKET control, SOCKET sock, const struct sockaddr_ipx *addr) {
@@ -579,11 +581,8 @@ static BOOL router_handle_call(struct router_vars *router, int sock, struct rout
579581
break;
580582
}
581583

582-
case rc_reuse: {
583-
if(!router_set_reuse(router, sock, call->sock, call->arg_int)) {
584-
ret.err_code = WSAEINVAL;
585-
}
586-
584+
case rc_flags: {
585+
ret.err_code = router_set_flags(router, sock, call->sock, call->arg_int);
587586
break;
588587
}
589588

@@ -879,14 +878,14 @@ BOOL rclient_set_filter(struct rclient *rclient, SOCKET sock, int ptype) {
879878
return FALSE;
880879
}
881880

882-
BOOL rclient_set_reuse(struct rclient *rclient, SOCKET sock, BOOL reuse) {
881+
BOOL rclient_set_flags(struct rclient *rclient, SOCKET sock, int flags) {
883882
if(rclient->sock != -1) {
884883
struct router_call call;
885884
struct router_ret ret;
886885

887-
call.call = rc_reuse;
886+
call.call = rc_flags;
888887
call.sock = sock;
889-
call.arg_int = reuse;
888+
call.arg_int = flags;
890889

891890
if(!rclient_do(rclient, &call, &ret)) {
892891
return FALSE;
@@ -895,11 +894,18 @@ BOOL rclient_set_reuse(struct rclient *rclient, SOCKET sock, BOOL reuse) {
895894
if(ret.err_code == ERROR_SUCCESS) {
896895
return TRUE;
897896
}else{
898-
WSASetLastError(WSAEINVAL);
897+
WSASetLastError(ret.err_code);
899898
return FALSE;
900899
}
901900
}else if(rclient->router) {
902-
router_set_reuse(rclient->router, 0, sock, reuse);
901+
int err = router_set_flags(rclient->router, 0, sock, flags);
902+
if(err == ERROR_SUCCESS) {
903+
return TRUE;
904+
}else{
905+
WSASetLastError(err);
906+
return FALSE;
907+
}
908+
903909
return TRUE;
904910
}
905911

src/router.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ struct router_call {
3131
rc_unbind,
3232
rc_port,
3333
rc_filter,
34-
rc_reuse,
34+
rc_flags,
3535
rc_remote
3636
} call;
3737

@@ -56,7 +56,7 @@ struct router_addr {
5656
SOCKET ws_socket; /* Application socket */
5757
SOCKET control_socket; /* Control socket */
5858
int filter_ptype; /* Packet type filter, negative to disable */
59-
BOOL reuse; /* SO_REUSEADDR */
59+
int flags;
6060

6161
/* Address of IP interface */
6262
uint32_t ipaddr;
@@ -118,11 +118,11 @@ BOOL rclient_init(struct rclient *rclient);
118118
BOOL rclient_start(struct rclient *rclient);
119119
void rclient_stop(struct rclient *rclient);
120120

121-
BOOL rclient_bind(struct rclient *rclient, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, BOOL reuse);
121+
BOOL rclient_bind(struct rclient *rclient, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, int flags);
122122
BOOL rclient_unbind(struct rclient *rclient, SOCKET sock);
123123
BOOL rclient_set_port(struct rclient *rclient, SOCKET sock, uint16_t port);
124124
BOOL rclient_set_filter(struct rclient *rclient, SOCKET sock, int ptype);
125-
BOOL rclient_set_reuse(struct rclient *rclient, SOCKET sock, BOOL reuse);
125+
BOOL rclient_set_flags(struct rclient *rclient, SOCKET sock, int flags);
126126
BOOL rclient_set_remote(struct rclient *rclient, SOCKET sock, const struct sockaddr_ipx *addr);
127127

128128
#endif /* !IPXWRAPPER_ROUTER_H */

src/winsock.c

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ SOCKET WSAAPI socket(int af, int type, int protocol) {
160160
return -1;
161161
}
162162

163-
nsock->flags = IPX_SEND | IPX_RECV;
163+
nsock->flags = IPX_SEND | IPX_RECV | IPX_RECV_BCAST;
164164
nsock->s_ptype = (protocol ? NSPROTO_IPX - protocol : 0);
165165

166166
lock_sockets();
@@ -544,6 +544,18 @@ int WSAAPI getsockopt(SOCKET fd, int level, int optname, char FAR *optval, int F
544544
return r_getsockopt(fd, level, optname, optval, optlen);
545545
}
546546

547+
#define SET_FLAG(flag, state) \
548+
if(state) { \
549+
sockptr->flags |= flag; \
550+
}else{ \
551+
sockptr->flags &= flag; \
552+
}
553+
554+
#define RC_SET_FLAG(flag, state) \
555+
if(sockptr->flags & IPX_BOUND && !rclient_set_flags(&g_rclient, fd, (sockptr->flags & ~(flag)) | ((state) ? (flag) : 0))) { \
556+
RETURN(-1); \
557+
}
558+
547559
int WSAAPI setsockopt(SOCKET fd, int level, int optname, const char FAR *optval, int optlen) {
548560
int *intval = (int*)optval;
549561
BOOL *bval = (BOOL*)optval;
@@ -578,28 +590,25 @@ int WSAAPI setsockopt(SOCKET fd, int level, int optname, const char FAR *optval,
578590
RETURN(0);
579591
}
580592

593+
if(optname == IPX_RECEIVE_BROADCAST) {
594+
RC_SET_FLAG(IPX_RECV_BCAST, *bval);
595+
SET_FLAG(IPX_RECV_BCAST, *bval);
596+
597+
RETURN(0);
598+
}
599+
581600
RETURN_WSA(WSAENOPROTOOPT, -1);
582601
}
583602

584603
if(level == SOL_SOCKET) {
585604
if(optname == SO_BROADCAST) {
586-
if(*bval) {
587-
sockptr->flags |= IPX_BROADCAST;
588-
}else{
589-
sockptr->flags &= ~IPX_BROADCAST;
590-
}
591-
605+
SET_FLAG(IPX_BROADCAST, *bval);
592606
RETURN(0);
593-
}else if(optname == SO_REUSEADDR) {
594-
if(sockptr->flags & IPX_BOUND && !rclient_set_reuse(&g_rclient, fd, *bval)) {
595-
RETURN(-1);
596-
}
597-
598-
if(*bval) {
599-
sockptr->flags |= IPX_REUSE;
600-
}else{
601-
sockptr->flags &= ~IPX_REUSE;
602-
}
607+
}
608+
609+
if(optname == SO_REUSEADDR) {
610+
RC_SET_FLAG(IPX_REUSE, *bval);
611+
SET_FLAG(IPX_REUSE, *bval);
603612

604613
RETURN(0);
605614
}

0 commit comments

Comments
 (0)