mirror of
https://github.com/solemnwarning/ipxwrapper
synced 2024-12-30 16:45:37 +01:00
Iterate over interface broadcast addresses in sendto rather than storing a
single address in ipx_socket during router bind.
This commit is contained in:
parent
f087fc26b1
commit
f72e88ea34
@ -220,6 +220,11 @@ ipx_interface_t *copy_ipx_interface(const ipx_interface_t *src)
|
||||
/* Free an ipx_interface structure and any memory allocated within. */
|
||||
void free_ipx_interface(ipx_interface_t *iface)
|
||||
{
|
||||
if(iface == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ipx_interface_ip_t *a, *a_tmp;
|
||||
|
||||
DL_FOREACH_SAFE(iface->ipaddr, a, a_tmp)
|
||||
|
@ -63,7 +63,6 @@ struct ipx_socket {
|
||||
|
||||
/* The following values are undefined when IPX_BOUND is not set */
|
||||
struct sockaddr_ipx addr;
|
||||
uint32_t nic_bcast;
|
||||
|
||||
/* Address used with connect call, only set when IPX_CONNECTED is */
|
||||
struct sockaddr_ipx remote_addr;
|
||||
|
11
src/router.c
11
src/router.c
@ -322,7 +322,7 @@ DWORD router_main(void *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, int flags) {
|
||||
static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr, int flags) {
|
||||
/* Network number 00:00:00:00 is specified as the "current" network, this code
|
||||
* treats it as a wildcard when used for the network OR node numbers.
|
||||
*
|
||||
@ -367,8 +367,6 @@ static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock,
|
||||
|
||||
/* TODO: Don't store the IP stuff here. */
|
||||
|
||||
*nic_bcast = iface->ipaddr->bcast;
|
||||
|
||||
uint32_t iface_ipaddr = iface->ipaddr->ipaddr;
|
||||
uint32_t iface_netmask = iface->ipaddr->netmask;
|
||||
|
||||
@ -575,7 +573,7 @@ static BOOL router_handle_call(struct router_vars *router, int sock, struct rout
|
||||
case rc_bind: {
|
||||
ret.ret_addr = call->arg_addr;
|
||||
|
||||
if(router_bind(router, sock, call->sock, &(ret.ret_addr), &(ret.ret_u32), call->arg_int) == -1) {
|
||||
if(router_bind(router, sock, call->sock, &(ret.ret_addr), call->arg_int) == -1) {
|
||||
ret.err_code = WSAGetLastError();
|
||||
}
|
||||
|
||||
@ -787,7 +785,7 @@ static BOOL rclient_do(struct rclient *rclient, struct router_call *call, struct
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rclient_bind(struct rclient *rclient, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, BOOL reuse) {
|
||||
BOOL rclient_bind(struct rclient *rclient, SOCKET sock, struct sockaddr_ipx *addr, BOOL reuse) {
|
||||
if(rclient->sock != -1) {
|
||||
struct router_call call;
|
||||
struct router_ret ret;
|
||||
@ -803,7 +801,6 @@ BOOL rclient_bind(struct rclient *rclient, SOCKET sock, struct sockaddr_ipx *add
|
||||
|
||||
if(ret.err_code == ERROR_SUCCESS) {
|
||||
*addr = ret.ret_addr;
|
||||
*nic_bcast = ret.ret_u32;
|
||||
|
||||
return TRUE;
|
||||
}else{
|
||||
@ -811,7 +808,7 @@ BOOL rclient_bind(struct rclient *rclient, SOCKET sock, struct sockaddr_ipx *add
|
||||
return FALSE;
|
||||
}
|
||||
}else if(rclient->router) {
|
||||
return router_bind(rclient->router, 0, sock, addr, nic_bcast, reuse) == 0 ? TRUE: FALSE;
|
||||
return router_bind(rclient->router, 0, sock, addr, reuse) == 0 ? TRUE: FALSE;
|
||||
}
|
||||
|
||||
log_printf(LOG_ERROR, "rclient_bind: No router?!");
|
||||
|
@ -118,7 +118,7 @@ BOOL rclient_init(struct rclient *rclient);
|
||||
BOOL rclient_start(struct rclient *rclient);
|
||||
void rclient_stop(struct rclient *rclient);
|
||||
|
||||
BOOL rclient_bind(struct rclient *rclient, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, int flags);
|
||||
BOOL rclient_bind(struct rclient *rclient, SOCKET sock, struct sockaddr_ipx *addr, int flags);
|
||||
BOOL rclient_unbind(struct rclient *rclient, SOCKET sock);
|
||||
BOOL rclient_set_port(struct rclient *rclient, SOCKET sock, uint16_t port);
|
||||
BOOL rclient_set_filter(struct rclient *rclient, SOCKET sock, int ptype);
|
||||
|
116
src/winsock.c
116
src/winsock.c
@ -249,7 +249,7 @@ int WSAAPI bind(SOCKET fd, const struct sockaddr *addr, int addrlen) {
|
||||
RETURN_WSA(WSAEINVAL, -1);
|
||||
}
|
||||
|
||||
if(!rclient_bind(&g_rclient, fd, &ipxaddr, &(ptr->nic_bcast), ptr->flags)) {
|
||||
if(!rclient_bind(&g_rclient, fd, &ipxaddr, ptr->flags)) {
|
||||
RETURN(-1);
|
||||
}
|
||||
|
||||
@ -708,6 +708,28 @@ int WSAAPI setsockopt(SOCKET fd, int level, int optname, const char FAR *optval,
|
||||
return r_setsockopt(fd, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
/* Send an IPX packet to the specified address.
|
||||
* Returns true on success, false on failure.
|
||||
*/
|
||||
static int send_packet(const ipx_packet *packet, int len, struct sockaddr *addr, int addrlen)
|
||||
{
|
||||
if(min_log_level <= LOG_DEBUG && addr->sa_family == AF_INET)
|
||||
{
|
||||
struct sockaddr_in *v4 = (struct sockaddr_in*)(addr);
|
||||
|
||||
IPX_STRING_ADDR(
|
||||
addr_s,
|
||||
addr32_in(packet->dest_net),
|
||||
addr48_in(packet->dest_node),
|
||||
packet->dest_socket
|
||||
);
|
||||
|
||||
log_printf(LOG_DEBUG, "Sending packet to %s (%s)", addr_s, inet_ntoa(v4->sin_addr));
|
||||
}
|
||||
|
||||
return (r_sendto(send_fd, (char*)packet, len, 0, addr, addrlen) == len);
|
||||
}
|
||||
|
||||
int WSAAPI sendto(SOCKET fd, const char *buf, int len, int flags, const struct sockaddr *addr, int addrlen) {
|
||||
struct sockaddr_ipx_ext *ipxaddr = (struct sockaddr_ipx_ext*)addr;
|
||||
|
||||
@ -780,36 +802,84 @@ int WSAAPI sendto(SOCKET fd, const char *buf, int len, int flags, const struct s
|
||||
SOCKADDR_STORAGE send_addr;
|
||||
size_t addrlen;
|
||||
|
||||
if(!addr_cache_get(&send_addr, &addrlen, addr32_in(packet->dest_net), addr48_in(packet->dest_node), packet->dest_socket))
|
||||
int success = 0;
|
||||
|
||||
if(addr_cache_get(&send_addr, &addrlen, addr32_in(packet->dest_net), addr48_in(packet->dest_node), packet->dest_socket))
|
||||
{
|
||||
/* Address is cached. We can send to the real host. */
|
||||
|
||||
success = send_packet(
|
||||
packet,
|
||||
psize,
|
||||
(struct sockaddr*)(&send_addr),
|
||||
addrlen
|
||||
);
|
||||
}
|
||||
else{
|
||||
/* No cached address. Send using broadcast. */
|
||||
|
||||
struct sockaddr_in *bcast = (struct sockaddr_in*)&send_addr;
|
||||
struct sockaddr_in bcast;
|
||||
|
||||
bcast->sin_family = AF_INET;
|
||||
bcast->sin_addr.s_addr = (main_config.bcast_all ? INADDR_BROADCAST : sockptr->nic_bcast);
|
||||
bcast->sin_port = htons(main_config.udp_port);
|
||||
bcast.sin_family = AF_INET;
|
||||
bcast.sin_port = htons(main_config.udp_port);
|
||||
|
||||
addrlen = sizeof(*bcast);
|
||||
}
|
||||
|
||||
if(min_log_level <= LOG_DEBUG) {
|
||||
/* TODO: Generic address display */
|
||||
|
||||
struct sockaddr_in *v4 = (struct sockaddr_in*)&send_addr;
|
||||
|
||||
IPX_STRING_ADDR(addr_s, addr32_in(packet->dest_net), addr48_in(packet->dest_node), packet->dest_socket);
|
||||
|
||||
log_printf(LOG_DEBUG, "Sending packet to %s (%s)", addr_s, inet_ntoa(v4->sin_addr));
|
||||
}
|
||||
|
||||
int sval = r_sendto(send_fd, (char*)packet, psize, 0, (struct sockaddr*)&send_addr, addrlen);
|
||||
if(sval == -1) {
|
||||
len = -1;
|
||||
if(main_config.bcast_all)
|
||||
{
|
||||
/* Broadcast on all interfaces. */
|
||||
|
||||
bcast.sin_addr.s_addr = htonl(INADDR_BROADCAST);
|
||||
|
||||
success = send_packet(
|
||||
packet,
|
||||
psize,
|
||||
(struct sockaddr*)(&bcast),
|
||||
sizeof(bcast)
|
||||
);
|
||||
}
|
||||
else{
|
||||
/* Broadcast on associated interfaces. */
|
||||
|
||||
ipx_interface_t *iface = ipx_interface_by_addr(
|
||||
addr32_in(packet->src_net),
|
||||
addr48_in(packet->src_node)
|
||||
);
|
||||
|
||||
if(iface && iface->ipaddr)
|
||||
{
|
||||
/* Iterate over all the IPs associated
|
||||
* with this interface and return
|
||||
* success if the packet makes it out
|
||||
* through any of them.
|
||||
*/
|
||||
|
||||
ipx_interface_ip_t* ip;
|
||||
|
||||
DL_FOREACH(iface->ipaddr, ip)
|
||||
{
|
||||
bcast.sin_addr.s_addr = ip->bcast;
|
||||
|
||||
success |= send_packet(
|
||||
packet,
|
||||
psize,
|
||||
(struct sockaddr*)(&bcast),
|
||||
sizeof(bcast)
|
||||
);
|
||||
}
|
||||
}
|
||||
else{
|
||||
/* No IP addresses. */
|
||||
|
||||
WSASetLastError(WSAENETDOWN);
|
||||
success = 0;
|
||||
}
|
||||
|
||||
free_ipx_interface(iface);
|
||||
}
|
||||
}
|
||||
|
||||
free(packet);
|
||||
RETURN(len);
|
||||
|
||||
RETURN(success ? len : -1);
|
||||
}else{
|
||||
return r_sendto(fd, buf, len, flags, addr, addrlen);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user