#include <bits/stdc++.h>
using namespace std;
bool Check(unsigned int N, int pos) { return (bool)(N & (1LL << pos)); }
long long Set(unsigned int N, int pos) { return N = N | (1LL << pos); }
bool chk(int x, int pos) { return (bool)(x & (1 << pos)); }
int Set(int x, int pos) { return x = x | (1 << pos); }
int clr(int x, int pos) { return x = x & ~(1 << pos); }
int n, m, srt[300005], ed[300005], lvl[300005], sz;
vector<int> v[300005];
int a[600005];
struct D {
  int x, k, lvl, lx, lk, llvl;
  bool lazy;
} tree[2400005];
void dfs(int u, int p) {
  lvl[u] = lvl[p] + 1;
  int i, x = v[u].size();
  srt[u] = ++sz;
  for (i = 0; i < x; i++) {
    if (p != v[u][i]) dfs(v[u][i], u);
  }
  ed[u] = ++sz;
}
void update_node(int idx, int b, int e, int x, int k, int lvl) {
  tree[idx].x += x, tree[idx].lx += x;
  if (tree[idx].x >= 1000000007) tree[idx].x %= 1000000007;
  if (tree[idx].lx >= 1000000007) tree[idx].lx %= 1000000007;
  tree[idx].k += k, tree[idx].lk += k;
  if (tree[idx].k >= 1000000007) tree[idx].k %= 1000000007;
  if (tree[idx].lk >= 1000000007) tree[idx].lk %= 1000000007;
  tree[idx].lvl += lvl;
  tree[idx].llvl += lvl;
  if (tree[idx].lvl >= 1000000007) tree[idx].lvl %= 1000000007;
  if (tree[idx].llvl >= 1000000007) tree[idx].llvl %= 1000000007;
  tree[idx].lazy = 1;
}
void lazy_update(int idx, int b, int e) {
  update_node((idx << 1), (b), ((b + e) >> 1), tree[idx].lx, tree[idx].lk,
              tree[idx].llvl);
  update_node(((idx << 1) + 1), (((b + e) >> 1) + 1), (e), tree[idx].lx,
              tree[idx].lk, tree[idx].llvl);
  tree[idx].lazy = tree[idx].lx = tree[idx].lk = tree[idx].llvl = 0;
}
int query(int idx, int b, int e, int st, int en) {
  if (b >= st && e <= en) {
    int ab = (1LL * a[b] * tree[idx].k) % 1000000007;
    return ((tree[idx].x + tree[idx].lvl) % 1000000007 - ab + 1000000007) %
           1000000007;
  }
  if (en < b || st > e) return 0;
  if (tree[idx].lazy) {
    lazy_update(idx, b, e);
  }
  int lft = query((idx << 1), (b), ((b + e) >> 1), st, en);
  int rgt = query(((idx << 1) + 1), (((b + e) >> 1) + 1), (e), st, en);
  return (lft + rgt);
}
void update(int idx, int b, int e, int st, int en, int x, int k, int lvl) {
  if (en < b || st > e) return;
  if (st <= b && en >= e) {
    update_node(idx, b, e, x, k, lvl);
    return;
  }
  if (tree[idx].lazy) lazy_update(idx, b, e);
  update((idx << 1), (b), ((b + e) >> 1), st, en, x, k, lvl);
  update(((idx << 1) + 1), (((b + e) >> 1) + 1), (e), st, en, x, k, lvl);
  return;
}
int main() {
  int ii, i, j, k, z = 0, c = 0, t, x, y, l, r, mid;
  scanf("%d", &n);
  for (i = 2; i <= n; i++) {
    scanf("%d", &x);
    v[x].push_back(i);
  }
  dfs(1, 0);
  for (i = 1; i <= n; i++) {
    a[srt[i]] = lvl[i];
  }
  scanf("%d", &m);
  for (i = 1; i <= m; i++) {
    scanf("%d", &t);
    if (t == 1) {
      scanf("%d", &n);
      scanf("%d", &x);
      scanf("%d", &k);
      int ne = (1LL * lvl[n] * k) % 1000000007;
      update(1, 1, sz, srt[n], ed[n], x, k, ne);
    } else {
      scanf("%d", &n);
      z = query(1, 1, sz, srt[n], srt[n]);
      printf("%d\n", z);
    }
  }
}
