SDAP: close TUN socket to unblock thread and clean interface shutdown
* Close entity->pdusession_sock manually before pthread_join() to unblock sdap_tun_read_thread() * Update tun_destroy() to open a fresh socket for interface management, independent from the data socket * Fix check on success of change_interface_state() in tun_destroy(): is a boolean * Handle ENODEV error when bringing interface down: treat as success if the interface is already gone. * tun_destroy() is now handling INTERFACE_DOWN, so `INTERFACE_DOWN` in `tun_config()` is no longer needed
This commit is contained in:
+19
-8
@@ -168,10 +168,14 @@ static bool change_interface_state(int sock_fd, const char *ifn, if_action_t if_
|
|||||||
|
|
||||||
struct ifreq ifr = {0};
|
struct ifreq ifr = {0};
|
||||||
strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name));
|
strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name));
|
||||||
|
|
||||||
/* get flags of this interface: see netdevice(7) */
|
/* get flags of this interface: see netdevice(7) */
|
||||||
bool success = ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t)&ifr) == 0;
|
bool success = ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t)&ifr) == 0;
|
||||||
if (!success)
|
if (!success && if_action == INTERFACE_DOWN && errno == ENODEV) {
|
||||||
goto fail_interface_state;
|
LOG_W(OIP, "trying to remove non-existant device %s\n", ifn);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOG_D(OIP, "Got flags for %s: 0x%x (action: %s)\n", ifn, ifr.ifr_flags, action);
|
||||||
|
|
||||||
if (if_action == INTERFACE_UP) {
|
if (if_action == INTERFACE_UP) {
|
||||||
ifr.ifr_flags |= IFF_UP | IFF_NOARP | IFF_POINTOPOINT;
|
ifr.ifr_flags |= IFF_UP | IFF_NOARP | IFF_POINTOPOINT;
|
||||||
@@ -183,6 +187,8 @@ static bool change_interface_state(int sock_fd, const char *ifn, if_action_t if_
|
|||||||
success = ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t)&ifr) == 0;
|
success = ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t)&ifr) == 0;
|
||||||
if (!success)
|
if (!success)
|
||||||
goto fail_interface_state;
|
goto fail_interface_state;
|
||||||
|
LOG_D(OIP, "Interface %s successfully set %s\n", ifn, action);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail_interface_state:
|
fail_interface_state:
|
||||||
@@ -201,10 +207,6 @@ bool tun_config(const char* ifname, const char *ipv4, const char *ipv6)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!change_interface_state(sock_fd, ifname, INTERFACE_DOWN)) {
|
|
||||||
close(sock_fd);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
if (ipv4 != NULL)
|
if (ipv4 != NULL)
|
||||||
success = setInterfaceParameter(sock_fd, ifname, AF_INET, ipv4, SIOCSIFADDR);
|
success = setInterfaceParameter(sock_fd, ifname, AF_INET, ipv4, SIOCSIFADDR);
|
||||||
@@ -272,8 +274,17 @@ int tun_generate_ue_ifname(char *ifname, int instance_id, int pdu_session_id)
|
|||||||
return snprintf(ifname, IFNAMSIZ, "%s%d%s", "oaitun_ue", instance_id + 1, pdu_session_id == -1 ? "" : pdu_session_string);
|
return snprintf(ifname, IFNAMSIZ, "%s%d%s", "oaitun_ue", instance_id + 1, pdu_session_id == -1 ? "" : pdu_session_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tun_destroy(const char *dev, int fd) {
|
void tun_destroy(const char *dev)
|
||||||
if (change_interface_state(fd, dev, INTERFACE_DOWN) == 0) {
|
{
|
||||||
|
// Use a new socket for ioctl operations
|
||||||
|
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (fd < 0) {
|
||||||
|
LOG_E(UTIL, "Failed to create socket for interface teardown: %d, %s\n", errno, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = change_interface_state(fd, dev, INTERFACE_DOWN);
|
||||||
|
if (success) {
|
||||||
LOG_I(UTIL, "Interface %s is now down.\n", dev);
|
LOG_I(UTIL, "Interface %s is now down.\n", dev);
|
||||||
} else {
|
} else {
|
||||||
LOG_E(UTIL, "Could not bring interface %s down.\n", dev);
|
LOG_E(UTIL, "Could not bring interface %s down.\n", dev);
|
||||||
|
|||||||
@@ -84,8 +84,7 @@ int tun_alloc(const char *dev);
|
|||||||
/*!
|
/*!
|
||||||
* \brief This function destroys the TUN interface
|
* \brief This function destroys the TUN interface
|
||||||
* \param[in] dev name of the interface
|
* \param[in] dev name of the interface
|
||||||
* \param[in] fd file descriptor of the allocated interface
|
|
||||||
*/
|
*/
|
||||||
void tun_destroy(const char *dev, int fd);
|
void tun_destroy(const char *dev);
|
||||||
|
|
||||||
#endif /*TUN_IF_H_*/
|
#endif /*TUN_IF_H_*/
|
||||||
|
|||||||
@@ -194,6 +194,10 @@ void remove_ip_if(nr_sdap_entity_t *entity)
|
|||||||
DevAssert(entity != NULL);
|
DevAssert(entity != NULL);
|
||||||
// Stop the read thread
|
// Stop the read thread
|
||||||
entity->stop_thread = true;
|
entity->stop_thread = true;
|
||||||
|
|
||||||
|
// Close the socket: read() will get EBADF and exit
|
||||||
|
close(entity->pdusession_sock);
|
||||||
|
|
||||||
int ret = pthread_join(entity->pdusession_thread, NULL);
|
int ret = pthread_join(entity->pdusession_thread, NULL);
|
||||||
AssertFatal(ret == 0, "pthread_join() failed, errno: %d, %s\n", errno, strerror(errno));
|
AssertFatal(ret == 0, "pthread_join() failed, errno: %d, %s\n", errno, strerror(errno));
|
||||||
// Bring down the IP interface
|
// Bring down the IP interface
|
||||||
@@ -205,5 +209,5 @@ void remove_ip_if(nr_sdap_entity_t *entity)
|
|||||||
} else {
|
} else {
|
||||||
tun_generate_ue_ifname(ifname, entity->ue_id, entity->pdusession_id != default_pdu ? entity->pdusession_id : -1);
|
tun_generate_ue_ifname(ifname, entity->ue_id, entity->pdusession_id != default_pdu ? entity->pdusession_id : -1);
|
||||||
}
|
}
|
||||||
tun_destroy(ifname, entity->pdusession_sock);
|
tun_destroy(ifname);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user