}
 
 /**
- * parse_options - build local/remote addresses from configuration
- * @attrs:     netlink config data
- * @ub:                UDP bearer instance
- * @local:     local bearer IP address/port
- * @remote:    peer or multicast IP/port
+ * tipc_parse_udp_addr - build udp media address from netlink data
+ * @nlattr:    netlink attribute containing sockaddr storage aligned address
+ * @addr:      tipc media address to fill with address, port and protocol type
+ * @scope_id:  IPv6 scope id pointer, not NULL indicates it's required
  */
-static int parse_options(struct nlattr *attrs[], struct udp_bearer *ub,
-                        struct udp_media_addr *local,
-                        struct udp_media_addr *remote)
+
+static int tipc_parse_udp_addr(struct nlattr *nla, struct udp_media_addr *addr,
+                              u32 *scope_id)
 {
-       struct nlattr *opts[TIPC_NLA_UDP_MAX + 1];
-       struct sockaddr_storage sa_local, sa_remote;
+       struct sockaddr_storage sa;
 
-       if (!attrs[TIPC_NLA_BEARER_UDP_OPTS])
-               goto err;
-       if (nla_parse_nested(opts, TIPC_NLA_UDP_MAX,
-                            attrs[TIPC_NLA_BEARER_UDP_OPTS],
-                            tipc_nl_udp_policy))
-               goto err;
-       if (opts[TIPC_NLA_UDP_LOCAL] && opts[TIPC_NLA_UDP_REMOTE]) {
-               nla_memcpy(&sa_local, opts[TIPC_NLA_UDP_LOCAL],
-                          sizeof(sa_local));
-               nla_memcpy(&sa_remote, opts[TIPC_NLA_UDP_REMOTE],
-                          sizeof(sa_remote));
-       } else {
-err:
-               pr_err("Invalid UDP bearer configuration");
-               return -EINVAL;
-       }
-       if ((sa_local.ss_family & sa_remote.ss_family) == AF_INET) {
-               struct sockaddr_in *ip4;
-
-               ip4 = (struct sockaddr_in *)&sa_local;
-               local->proto = htons(ETH_P_IP);
-               local->port = ip4->sin_port;
-               local->ipv4.s_addr = ip4->sin_addr.s_addr;
-
-               ip4 = (struct sockaddr_in *)&sa_remote;
-               remote->proto = htons(ETH_P_IP);
-               remote->port = ip4->sin_port;
-               remote->ipv4.s_addr = ip4->sin_addr.s_addr;
+       nla_memcpy(&sa, nla, sizeof(sa));
+       if (sa.ss_family == AF_INET) {
+               struct sockaddr_in *ip4 = (struct sockaddr_in *)&sa;
+
+               addr->proto = htons(ETH_P_IP);
+               addr->port = ip4->sin_port;
+               addr->ipv4.s_addr = ip4->sin_addr.s_addr;
                return 0;
 
 #if IS_ENABLED(CONFIG_IPV6)
-       } else if ((sa_local.ss_family & sa_remote.ss_family) == AF_INET6) {
-               int atype;
-               struct sockaddr_in6 *ip6;
-
-               ip6 = (struct sockaddr_in6 *)&sa_local;
-               atype = ipv6_addr_type(&ip6->sin6_addr);
-               if (__ipv6_addr_needs_scope_id(atype) && !ip6->sin6_scope_id)
-                       return -EINVAL;
-
-               local->proto = htons(ETH_P_IPV6);
-               local->port = ip6->sin6_port;
-               memcpy(&local->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr));
-               ub->ifindex = ip6->sin6_scope_id;
-
-               ip6 = (struct sockaddr_in6 *)&sa_remote;
-               remote->proto = htons(ETH_P_IPV6);
-               remote->port = ip6->sin6_port;
-               memcpy(&remote->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr));
+       } else if (sa.ss_family == AF_INET6) {
+               struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)&sa;
+
+               addr->proto = htons(ETH_P_IPV6);
+               addr->port = ip6->sin6_port;
+               memcpy(&addr->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr));
+
+               /* Scope ID is only interesting for local addresses */
+               if (scope_id) {
+                       int atype;
+
+                       atype = ipv6_addr_type(&ip6->sin6_addr);
+                       if (__ipv6_addr_needs_scope_id(atype) &&
+                           !ip6->sin6_scope_id) {
+                               return -EINVAL;
+                       }
+
+                       *scope_id = ip6->sin6_scope_id ? : 0;
+               }
+
                return 0;
 #endif
        }
        struct udp_media_addr local = {0};
        struct udp_port_cfg udp_conf = {0};
        struct udp_tunnel_sock_cfg tuncfg = {NULL};
+       struct nlattr *opts[TIPC_NLA_UDP_MAX + 1];
 
        ub = kzalloc(sizeof(*ub), GFP_ATOMIC);
        if (!ub)
                return -ENOMEM;
 
+       if (!attrs[TIPC_NLA_BEARER_UDP_OPTS])
+               goto err;
+
+       if (nla_parse_nested(opts, TIPC_NLA_UDP_MAX,
+                            attrs[TIPC_NLA_BEARER_UDP_OPTS],
+                            tipc_nl_udp_policy))
+               goto err;
+
+       if (!opts[TIPC_NLA_UDP_LOCAL] || !opts[TIPC_NLA_UDP_REMOTE]) {
+               pr_err("Invalid UDP bearer configuration");
+               return -EINVAL;
+       }
+
+       err = tipc_parse_udp_addr(opts[TIPC_NLA_UDP_LOCAL], &local,
+                                 &ub->ifindex);
+       if (err)
+               goto err;
+
        remote = (struct udp_media_addr *)&b->bcast_addr.value;
        memset(remote, 0, sizeof(struct udp_media_addr));
-       err = parse_options(attrs, ub, &local, remote);
+       err = tipc_parse_udp_addr(opts[TIPC_NLA_UDP_REMOTE], remote, NULL);
        if (err)
                goto err;