#include <bits/stdc++.h>
using namespace std;
inline long long read() {
  long long x = 0, f = 1;
  char c;
  for (; !isdigit(c); c = getchar())
    if (c == '-') f = -1;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  return x * f;
}
long long n, m, fa[300005], size[300005], son[300005], dep[300005], seg[300005],
    rev[300005], top[300005];
const long long mod = 1e9 + 7;
vector<long long> G[300005];
struct node {
  long long lazy, l, r, sum;
};
struct Segment_tree {
  node tree[1200005];
  void build(long long x, long long l, long long r) {
    tree[x].l = l, tree[x].r = r;
    if (l == r) return;
    long long mid = (l + r) >> 1;
    build(x << 1, l, mid);
    build(x << 1 | 1, mid + 1, r);
  }
  void push_down(long long x) {
    if (tree[x].lazy) {
      tree[x << 1].lazy = (tree[x << 1].lazy + tree[x].lazy) % mod;
      tree[x << 1 | 1].lazy = (tree[x << 1 | 1].lazy + tree[x].lazy) % mod;
      tree[x << 1].sum =
          (tree[x << 1].sum +
           (1ll * (tree[x << 1].r - tree[x << 1].l + 1) * tree[x].lazy % mod)) %
          mod;
      tree[x << 1 | 1].sum =
          (tree[x << 1 | 1].sum +
           (1ll * (tree[x << 1 | 1].r - tree[x << 1 | 1].l + 1) * tree[x].lazy %
            mod)) %
          mod;
      tree[x].lazy = 0;
    }
  }
  void updata(long long x, long long l, long long r, long long L, long long R,
              long long y) {
    if (L <= l && r <= R) {
      tree[x].sum =
          (tree[x].sum + (1ll * (tree[x].r - tree[x].l + 1) * y % mod)) % mod;
      tree[x].lazy = (tree[x].lazy + y) % mod;
      return;
    }
    long long mid = (l + r) >> 1;
    push_down(x);
    if (L <= mid) updata(x << 1, l, mid, L, R, y);
    if (mid + 1 <= R) updata(x << 1 | 1, mid + 1, r, L, R, y);
    tree[x].sum = (tree[x << 1].sum + tree[x << 1 | 1].sum) % mod;
  }
  long long query(long long x, long long l, long long r, long long L,
                  long long R) {
    if (L <= l && r <= R) return tree[x].sum;
    long long mid = (l + r) >> 1, ans = 0;
    push_down(x);
    if (L <= mid) ans = (ans + query(x << 1, l, mid, L, R)) % mod;
    if (mid + 1 <= R) ans = (ans + query(x << 1 | 1, mid + 1, r, L, R)) % mod;
    return ans;
  }
};
struct TCT {
  Segment_tree S;
  void add_tree(long long u, long long x) {
    S.updata(1, 1, n, seg[u], seg[u] + size[u] - 1, x);
  }
  long long query(long long u) { return S.query(1, 1, n, seg[u], seg[u]); }
} A, B;
void dfs1(long long u, long long f) {
  dep[u] = dep[f] + 1, fa[u] = f, size[u] = 1;
  for (long long i = 0; i < G[u].size(); i++) {
    long long v = G[u][i];
    if (v == f) continue;
    dfs1(v, u);
    size[u] += size[v];
    if (size[v] > size[son[u]]) son[u] = v;
  }
}
void dfs2(long long u, long long f) {
  if (son[u]) {
    seg[son[u]] = ++seg[0];
    top[son[u]] = top[u];
    rev[seg[0]] = son[u];
    dfs2(son[u], u);
  }
  for (long long i = 0; i < G[u].size(); i++) {
    long long v = G[u][i];
    if (v == f || v == son[u]) continue;
    seg[v] = ++seg[0];
    top[v] = v;
    rev[seg[0]] = v;
    dfs2(v, u);
  }
}
signed main() {
  n = read();
  for (long long i = 2; i <= n; i++) {
    long long fa;
    fa = read();
    G[fa].push_back(i);
    G[i].push_back(fa);
  }
  dfs1(1, 0);
  seg[0] = rev[1] = top[1] = seg[1] = 1;
  dfs2(1, 0);
  A.S.build(1, 1, n), B.S.build(1, 1, n);
  m = read();
  for (long long i = 1; i <= m; i++) {
    long long opt, v, x, k;
    opt = read();
    if (opt == 1) {
      v = read(), x = read(), k = read();
      A.add_tree(v, ((x + (dep[v] * k % mod)) % mod + mod) % mod);
      B.add_tree(v, k);
    } else {
      v = read();
      printf("%lld\n",
             ((A.query(v) - (B.query(v) * dep[v] % mod)) % mod + mod) % mod);
    }
  }
  return 0;
}
