diff --git a/srsue/src/upper/gw.cc b/srsue/src/upper/gw.cc index a7e2df161..b6a620462 100644 --- a/srsue/src/upper/gw.cc +++ b/srsue/src/upper/gw.cc @@ -335,6 +335,9 @@ srslte::error_t gw::init_if(char *err_str) char addr_str[INET6_ADDRSTRLEN]; if(find_ipv6_addr(&in6p)){ gw_log->debug("Found link-local IPv6 address: %s\n",inet_ntop(AF_INET6, &in6p, addr_str,INET6_ADDRSTRLEN) ); + del_ipv6_addr(&in6p); + } else { + gw_log->warning("Could not find link-local IPv6 address.\n"); } if_up = true; @@ -562,5 +565,59 @@ out: return true; } -void gw::del_ipv6_addr(struct in6_addr *in6p) {} +void gw::del_ipv6_addr(struct in6_addr *in6p) +{ + int status, fd =-1; + unsigned int if_index; + struct { + struct nlmsghdr n; + struct ifaddrmsg ifa; + char buf[1024]; + } req; + + //Get Interface Index + if_index = if_nametoindex(tundevname.c_str()); + if(if_index == 0){ + gw_log->error("Could not find interface index\n"); + goto out; + } + + // Open netlink socket + fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + gw_log->error("Error openning NETLINK socket -- %s\n", strerror(errno)); + goto out; + } + + // We use RTM_DELADDR to delete the ip address from the interface + memset(&req, 0, sizeof(req)); + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + req.n.nlmsg_type = RTM_DELADDR; + req.n.nlmsg_flags = NLM_F_REQUEST; + + req.ifa.ifa_family = AF_INET6; + req.ifa.ifa_prefixlen = 64; + req.ifa.ifa_index = if_index; // set the tun_srsue index + req.ifa.ifa_scope = 0; + + //Add RT atribute + struct rtattr *rta; + rta = (struct rtattr *)(((char *)&req.n) + NLMSG_ALIGN(req.n.nlmsg_len)); + rta->rta_type = IFA_LOCAL; + rta->rta_len = RTA_LENGTH(16); + memcpy(RTA_DATA(rta), in6p, 16); + req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + rta->rta_len; + + status = send(fd, &req, req.n.nlmsg_len, 0); + if (status < 0) { + gw_log->error("Error sending NETLINK message\n"); + goto out; + } + +out: + if (fd<0){ + close(fd); + } + return; +} } // namespace srsue diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 0533f11e6..0304ab5e4 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -641,7 +641,7 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { nas_log->warning("Requested IPv4v6, but only received a single PDN address.\n"); nas_log->warning("EMM Cause: %d\n", attach_accept.emm_cause ); } - if (LIBLTE_MME_PDN_TYPE_IPV4 == act_def_eps_bearer_context_req.pdn_addr.pdn_type || LIBLTE_MME_PDN_TYPE_IPV4V6 == act_def_eps_bearer_context_req.pdn_addr.pdn_type) { + if (LIBLTE_MME_PDN_TYPE_IPV4 == act_def_eps_bearer_context_req.pdn_addr.pdn_type) { ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[0] << 24; ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[1] << 16; ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[2] << 8; @@ -665,7 +665,7 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { if (gw->setup_if_addr(ip_addr, err_str)) { nas_log->error("Failed to set gateway address - %s\n", err_str); } - } else if (LIBLTE_MME_PDN_TYPE_IPV6 == act_def_eps_bearer_context_req.pdn_addr.pdn_type || LIBLTE_MME_PDN_TYPE_IPV4V6 == act_def_eps_bearer_context_req.pdn_addr.pdn_type){ + } else if (LIBLTE_MME_PDN_TYPE_IPV6 == act_def_eps_bearer_context_req.pdn_addr.pdn_type){ memcpy(ipv6_if_id, act_def_eps_bearer_context_req.pdn_addr.addr, 8); nas_log->info("Network attach successful. APN: %s, IPv6 interface id: %02x%02x:%02x%02x:%02x%02x:%02x%02x\n", act_def_eps_bearer_context_req.apn.apn, @@ -692,6 +692,54 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { if (gw->setup_if_addr6(ipv6_if_id, err_str)) { nas_log->error("Failed to set gateway address - %s\n", err_str); } + } else if (LIBLTE_MME_PDN_TYPE_IPV4V6 == act_def_eps_bearer_context_req.pdn_addr.pdn_type){ + memcpy(ipv6_if_id, act_def_eps_bearer_context_req.pdn_addr.addr, 8); + //IPv6 + nas_log->info("Network attach successful. APN: %s, IPv6 interface id: %02x%02x:%02x%02x:%02x%02x:%02x%02x\n", + act_def_eps_bearer_context_req.apn.apn, + act_def_eps_bearer_context_req.pdn_addr.addr[0], + act_def_eps_bearer_context_req.pdn_addr.addr[1], + act_def_eps_bearer_context_req.pdn_addr.addr[2], + act_def_eps_bearer_context_req.pdn_addr.addr[3], + act_def_eps_bearer_context_req.pdn_addr.addr[4], + act_def_eps_bearer_context_req.pdn_addr.addr[5], + act_def_eps_bearer_context_req.pdn_addr.addr[6], + act_def_eps_bearer_context_req.pdn_addr.addr[7]); + nas_log->console("Network attach successful. IPv6 interface Id: %02x%02x:%02x%02x:%02x%02x:%02x%02x\n", + act_def_eps_bearer_context_req.pdn_addr.addr[0], + act_def_eps_bearer_context_req.pdn_addr.addr[1], + act_def_eps_bearer_context_req.pdn_addr.addr[2], + act_def_eps_bearer_context_req.pdn_addr.addr[3], + act_def_eps_bearer_context_req.pdn_addr.addr[4], + act_def_eps_bearer_context_req.pdn_addr.addr[5], + act_def_eps_bearer_context_req.pdn_addr.addr[6], + act_def_eps_bearer_context_req.pdn_addr.addr[7]); + //IPv4 + ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[8] << 24; + ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[9] << 16; + ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[10] << 8; + ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[11]; + + nas_log->info("Network attach successful. APN: %s, IP: %u.%u.%u.%u\n", + act_def_eps_bearer_context_req.apn.apn, + act_def_eps_bearer_context_req.pdn_addr.addr[8], + act_def_eps_bearer_context_req.pdn_addr.addr[9], + act_def_eps_bearer_context_req.pdn_addr.addr[10], + act_def_eps_bearer_context_req.pdn_addr.addr[11]); + + nas_log->console("Network attach successful. IP: %u.%u.%u.%u\n", + act_def_eps_bearer_context_req.pdn_addr.addr[8], + act_def_eps_bearer_context_req.pdn_addr.addr[9], + act_def_eps_bearer_context_req.pdn_addr.addr[10], + act_def_eps_bearer_context_req.pdn_addr.addr[11]); + + char *err_str = NULL; + if (gw->setup_if_addr(ip_addr, err_str)) { + nas_log->error("Failed to set gateway address - %s\n", err_str); + } + if (gw->setup_if_addr6(ipv6_if_id, err_str)) { + nas_log->error("Failed to set gateway address - %s\n", err_str); + } } else { nas_log->error("PDN type not IPv4, IPv6 nor IPv4v6\n"); pool->deallocate(pdu);