diff --git a/src/interface.c b/src/interface.c index 19f77fc..3928a97 100644 --- a/src/interface.c +++ b/src/interface.c @@ -17,6 +17,7 @@ #include #include +#include #include "interface.h" #include "common.h" @@ -92,23 +93,55 @@ ipx_interface_t *get_interfaces(int ifnum) continue; } - struct ipx_interface *nnic = malloc(sizeof(struct ipx_interface)); - if(!nnic) + ipx_interface_t *iface = malloc(sizeof(ipx_interface_t)); + if(!iface) { log_printf(LOG_ERROR, "Couldn't allocate ipx_interface!"); - free_interfaces(nics); + free_ipx_interfaces(&nics); return NULL; } - nnic->ipaddr = inet_addr(ifptr->IpAddressList.IpAddress.String); - nnic->netmask = inet_addr(ifptr->IpAddressList.IpMask.String); - nnic->bcast = nnic->ipaddr | ~nnic->netmask; + iface->ipaddr = NULL; - nnic->hwaddr = hwaddr; + IP_ADDR_STRING *ip_ptr = &(ifptr->IpAddressList); - nnic->ipx_net = config.netnum; - nnic->ipx_node = config.nodenum; + for(; ip_ptr; ip_ptr = ip_ptr->Next) + { + uint32_t ipaddr = inet_addr(ip_ptr->IpAddress.String); + uint32_t netmask = inet_addr(ip_ptr->IpMask.String); + + if(ipaddr == 0) + { + /* No IP address. + * Because an empty linked list would be silly. + */ + + continue; + } + + ipx_interface_ip_t *addr = malloc(sizeof(ipx_interface_ip_t)); + if(!addr) + { + log_printf(LOG_ERROR, "Couldn't allocate ipx_interface_ip!"); + + free_ipx_interface(iface); + free_ipx_interfaces(&nics); + + continue; + } + + addr->ipaddr = ipaddr; + addr->netmask = netmask; + addr->bcast = ipaddr | (~netmask); + + DL_APPEND(iface->ipaddr, addr); + } + + iface->hwaddr = hwaddr; + + iface->ipx_net = config.netnum; + iface->ipx_node = config.nodenum; /* Workaround for buggy versions of Hamachi that don't initialise * the interface hardware address correctly. @@ -116,27 +149,31 @@ ipx_interface_t *get_interfaces(int ifnum) unsigned char hamachi_bug[] = {0x7A, 0x79, 0x00, 0x00, 0x00, 0x00}; - if(nnic->ipx_node == addr48_in(hamachi_bug)) + if(iface->ipx_node == addr48_in(hamachi_bug) && iface->ipaddr) { log_printf(LOG_WARNING, "Invalid Hamachi interface detected, correcting node number"); - addr32_out(hamachi_bug + 2, nnic->ipaddr); - nnic->ipx_node = addr48_in(hamachi_bug); + addr32_out(hamachi_bug + 2, iface->ipaddr->ipaddr); + iface->ipx_node = addr48_in(hamachi_bug); } - if(nnic->hwaddr == primary) + if(iface->hwaddr == primary) { /* Primary interface, insert at the start of the list */ - DL_PREPEND(nics, nnic); + DL_PREPEND(nics, iface); } else{ - DL_APPEND(nics, nnic); + DL_APPEND(nics, iface); } } free(ifroot); - /* Delete every entry in the NIC list except the requested one */ + /* Delete every entry in the NIC list except the requested one. + * + * This is done here rather than when building the list as the primary + * interface may change the indexes if it isn't the first. + */ if(ifnum >= 0) { @@ -148,7 +185,7 @@ ipx_interface_t *get_interfaces(int ifnum) if(this_ifnum++ != ifnum) { DL_DELETE(nics, iface); - free(iface); + free_ipx_interface(iface); } } } @@ -156,13 +193,28 @@ ipx_interface_t *get_interfaces(int ifnum) return nics; } -void free_interfaces(ipx_interface_t *list) +/* Free an ipx_interface structure and any memory allocated within. */ +void free_ipx_interface(ipx_interface_t *iface) +{ + ipx_interface_ip_t *a, *a_tmp; + + DL_FOREACH_SAFE(iface->ipaddr, a, a_tmp) + { + DL_DELETE(iface->ipaddr, a); + free(a); + } + + free(iface); +} + +/* Free a list of ipx_interface structures */ +void free_ipx_interfaces(ipx_interface_t **list) { ipx_interface_t *iface, *tmp; - DL_FOREACH_SAFE(list, iface, tmp) + DL_FOREACH_SAFE(*list, iface, tmp) { - DL_DELETE(list, iface); - free(iface); + DL_DELETE(*list, iface); + free_ipx_interface(iface); } } diff --git a/src/interface.h b/src/interface.h index db17a12..4a07c16 100644 --- a/src/interface.h +++ b/src/interface.h @@ -23,23 +23,44 @@ #include "common.h" -typedef struct ipx_interface ipx_interface_t; +#ifdef __cplusplus +extern "C" { +#endif -struct ipx_interface { +typedef struct ipx_interface_ip ipx_interface_ip_t; + +struct ipx_interface_ip { uint32_t ipaddr; uint32_t netmask; uint32_t bcast; + ipx_interface_ip_t *prev; + ipx_interface_ip_t *next; +}; + +typedef struct ipx_interface ipx_interface_t; + +struct ipx_interface { addr48_t hwaddr; addr32_t ipx_net; addr48_t ipx_node; + ipx_interface_ip_t *ipaddr; + ipx_interface_t *prev; ipx_interface_t *next; }; +IP_ADAPTER_INFO *get_sys_interfaces(void); + ipx_interface_t *get_interfaces(int ifnum); -void free_interfaces(ipx_interface_t *iface); + +void free_ipx_interface(ipx_interface_t *iface); +void free_ipx_interfaces(ipx_interface_t **list); + +#ifdef __cplusplus +} +#endif #endif /* !IPXWRAPPER_INTERFACE_H */ diff --git a/src/ipxwrapper.c b/src/ipxwrapper.c index 1377063..014f17c 100644 --- a/src/ipxwrapper.c +++ b/src/ipxwrapper.c @@ -196,20 +196,26 @@ BOOL ip_is_local(uint32_t ipaddr) { struct ipx_interface *i = ifaces; while(i) { + /* TODO: Rewrite. */ + if(!i->ipaddr) + { + continue; + } + struct ipaddr_list *nn = malloc(sizeof(struct ipaddr_list)); if(!nn) { log_printf(LOG_ERROR, "Out of memory! Can't allocate ipaddr_list structure!"); break; } - nn->ipaddr = i->ipaddr; + nn->ipaddr = i->ipaddr->ipaddr; nn->next = local_addrs; local_addrs = nn; i = i->next; } - free_interfaces(ifaces); + free_ipx_interfaces(&ifaces); local_updated = time(NULL); } diff --git a/src/router.c b/src/router.c index f1b7c94..5a6ec52 100644 --- a/src/router.c +++ b/src/router.c @@ -345,6 +345,9 @@ static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, if( (sa_netnum == iface->ipx_net || sa_netnum == 0) && (sa_nodenum == iface->ipx_node || sa_nodenum == 0) + + /* TODO: Remove this check. */ + && iface->ipaddr ) { break; } @@ -353,7 +356,7 @@ static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, if(!iface) { log_printf(LOG_ERROR, "bind failed: no such address"); - free_interfaces(ifaces); + free_ipx_interfaces(&ifaces); WSASetLastError(WSAEADDRNOTAVAIL); return -1; @@ -362,12 +365,14 @@ static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, addr32_out(addr->sa_netnum, iface->ipx_net); addr48_out(addr->sa_nodenum, iface->ipx_node); - *nic_bcast = iface->bcast; + /* TODO: Don't store the IP stuff here. */ - uint32_t iface_ipaddr = iface->ipaddr; - uint32_t iface_netmask = iface->netmask; + *nic_bcast = iface->ipaddr->bcast; - free_interfaces(ifaces); + uint32_t iface_ipaddr = iface->ipaddr->ipaddr; + uint32_t iface_netmask = iface->ipaddr->netmask; + + free_ipx_interfaces(&ifaces); EnterCriticalSection(&(router->crit_sec)); diff --git a/src/winsock.c b/src/winsock.c index 455cc96..479a85c 100644 --- a/src/winsock.c +++ b/src/winsock.c @@ -539,7 +539,7 @@ int WSAAPI getsockopt(SOCKET fd, int level, int optname, char FAR *optval, int F ipxdata->maxpkt = MAX_DATA_SIZE; ipxdata->linkspeed = 100000; /* 10MBps */ - free_interfaces(nic); + free_ipx_interface(nic); RETURN(0); } @@ -561,7 +561,7 @@ int WSAAPI getsockopt(SOCKET fd, int level, int optname, char FAR *optval, int F nic = nic->next; } - free_interfaces(ifaces); + free_ipx_interfaces(&ifaces); RETURN(0); }