#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 500;
const long long mod = 1e9 + 7;
struct Edge {
  int v, nxt;
} e[maxn << 1];
int n, q, in[maxn], out[maxn], deep[maxn], tot, head[maxn], dfs_clock;
inline void check(long long &x) {
  if (x < 0) x += mod;
  if (x >= mod) x %= mod;
}
struct Segmenttree {
  struct treenode {
    int L, R, s;
    long long deep_sum, lazy1, lazy2, ans;
    void updata(long long x, long long y) {
      int s = R - L + 1;
      ans += (1LL * s * x) % mod;
      check(ans);
      ans -= (1LL * deep_sum * y) % mod;
      check(ans);
      lazy1 += x, lazy2 += y;
      check(lazy1);
      check(lazy2);
    }
  };
  treenode tree[maxn * 4];
  inline void push_down(int o) {
    int lson = o << 1, rson = o << 1 | 1;
    tree[lson].updata(tree[o].lazy1, tree[o].lazy2);
    tree[rson].updata(tree[o].lazy1, tree[o].lazy2);
    tree[o].lazy1 = tree[o].lazy2 = 0;
  }
  void build(int L, int R, int o) {
    tree[o].L = L, tree[o].R = R,
    tree[o].deep_sum = tree[o].lazy1 = tree[o].lazy2 = tree[o].ans = 0;
    if (R > L) {
      int mid = (L + R) >> 1;
      build(L, mid, o << 1);
      build(mid + 1, R, o << 1 | 1);
    }
  }
  void push_up(int o) {
    int lson = o << 1, rson = o << 1 | 1;
    tree[o].deep_sum = tree[lson].deep_sum + tree[rson].deep_sum;
    check(tree[o].deep_sum);
  }
  void updata(int QL, int QR, long long a, long long b, int o) {
    int L = tree[o].L, R = tree[o].R;
    if (QL <= L && R <= QR)
      tree[o].updata(a, b);
    else {
      int mid = (L + R) >> 1;
      if (QL <= mid) updata(QL, QR, a, b, o << 1);
      if (QR > mid) updata(QL, QR, a, b, o << 1 | 1);
    }
  }
  void init_updata(int p, int v, int o) {
    int L = tree[o].L, R = tree[o].R;
    if (L == R)
      tree[o].deep_sum += v;
    else {
      int mid = (L + R) >> 1;
      if (p <= mid)
        init_updata(p, v, o << 1);
      else
        init_updata(p, v, o << 1 | 1);
      push_up(o);
    }
  }
  long long query(int p, int o) {
    int L = tree[o].L, R = tree[o].R;
    if (L == R)
      return tree[o].ans;
    else {
      push_down(o);
      int mid = (L + R) >> 1;
      if (p <= mid)
        return query(p, o << 1);
      else
        query(p, o << 1 | 1);
    }
  }
} Sgtree;
void addedge(int u, int v) {
  e[tot].v = v, e[tot].nxt = head[u], head[u] = tot++;
}
void dfs(int u) {
  in[u] = ++dfs_clock;
  int s = 1;
  Sgtree.init_updata(in[u], deep[u], 1);
  for (int i = head[u]; ~i; i = e[i].nxt) {
    int v = e[i].v;
    deep[v] = deep[u] + 1;
    dfs(v);
  }
  out[u] = dfs_clock;
}
int main(int argc, char *argv[]) {
  scanf("%d", &n);
  Sgtree.build(1, n, 1);
  memset(head, -1, sizeof(head));
  for (int i = 2; i <= n; ++i) {
    int fa;
    scanf("%d", &fa);
    addedge(fa, i);
  }
  dfs(1);
  scanf("%d", &q);
  while (q--) {
    int a, b, x, k;
    scanf("%d%d", &a, &b);
    if (a == 2)
      printf("%I64d\n", Sgtree.query(in[b], 1));
    else {
      scanf("%d%d", &x, &k);
      Sgtree.updata(in[b], out[b], (x + 1LL * deep[b] * k) % mod, k, 1);
    }
  }
  return 0;
}
