void lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt) { if (ospf2) { struct ospf_lsa_ext2 *ext = en->lsa_body; rt->ip = ipa_from_u32(en->lsa.id & ext->netmask); rt->pxlen = u32_masklen(ext->netmask); rt->pxopts = 0; rt->metric = ext->metric & LSA_METRIC_MASK; rt->ebit = ext->metric & LSA_EXT2_EBIT; rt->fbit = ext->fwaddr; rt->fwaddr = ipa_from_u32(ext->fwaddr); rt->tag = ext->tag; rt->propagate = lsa_get_options(&en->lsa) & OPT_P; } else { struct ospf_lsa_ext3 *ext = en->lsa_body; u16 rest; u32 *buf = lsa_get_ipv6_prefix(ext->rest, &rt->ip, &rt->pxlen, &rt->pxopts, &rest); rt->metric = ext->metric & LSA_METRIC_MASK; rt->ebit = ext->metric & LSA_EXT3_EBIT; rt->fbit = ext->metric & LSA_EXT3_FBIT; if (rt->fbit) buf = lsa_get_ipv6_addr(buf, &rt->fwaddr); else rt->fwaddr = IPA_NONE; rt->tag = (ext->metric & LSA_EXT3_TBIT) ? *buf++ : 0; rt->propagate = rt->pxopts & OPT_PX_P; } }
void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric) { if (ospf2) { struct ospf_lsa_sum2 *ls = en->lsa_body; *ip = ipa_from_u32(en->lsa.id & ls->netmask); *pxlen = u32_masklen(ls->netmask); *pxopts = 0; *metric = ls->metric & LSA_METRIC_MASK; } else { struct ospf_lsa_sum3_net *ls = en->lsa_body; u16 rest; lsa_get_ipv6_prefix(ls->prefix, ip, pxlen, pxopts, &rest); *metric = ls->metric & LSA_METRIC_MASK; } }
static void krt_parse_entry(byte *ent, struct krt_proto *p) { u32 dest0, gw0, mask0; ip_addr dest, gw, mask; unsigned int flags; int masklen; net *net; byte *iface = ent; rte *e; if (sscanf(ent, "%*s\t%x\t%x\t%x\t%*d\t%*d\t%*d\t%x\t", &dest0, &gw0, &flags, &mask0) != 4) { log(L_ERR "krt read: unable to parse `%s'", ent); return; } while (*ent != '\t') ent++; *ent = 0; dest = ipa_from_u32(dest0); ipa_ntoh(dest); gw = ipa_from_u32(gw0); ipa_ntoh(gw); mask = ipa_from_u32(mask0); ipa_ntoh(mask); if ((masklen = ipa_mklen(mask)) < 0) { log(L_ERR "krt read: invalid netmask %08x", mask0); return; } DBG("Got %I/%d via %I flags %x\n", dest, masklen, gw, flags); if (!(flags & RTF_UP)) { DBG("Down.\n"); return; } if (flags & RTF_HOST) masklen = 32; if (flags & (RTF_DYNAMIC | RTF_MODIFIED)) /* Redirect route */ { log(L_WARN "krt: Ignoring redirect to %I/%d via %I", dest, masklen, gw); return; } net = net_get(p->p.table, dest, masklen); rta a = { .proto = &p->p, .source = RTS_INHERIT, .scope = SCOPE_UNIVERSE, .cast = RTC_UNICAST }; if (flags & RTF_GATEWAY) { neighbor *ng = neigh_find(&p->p, &gw, 0); if (ng && ng->scope) a.iface = ng->iface; else { log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", gw, net->n.prefix, net->n.pxlen); return; } a.dest = RTD_ROUTER; a.gw = gw; } else if (flags & RTF_REJECT) { a.dest = RTD_UNREACHABLE; a.gw = IPA_NONE; } else if (isalpha(iface[0])) { a.dest = RTD_DEVICE; a.gw = IPA_NONE; a.iface = krt_temp_iface(p, iface); } else { log(L_WARN "Kernel reporting unknown route type to %I/%d", net->n.prefix, net->n.pxlen); return; } e = rte_get_temp(&a); e->net = net; e->u.krt.src = KRT_SRC_UNKNOWN; krt_got_route(p, e); } void krt_scan_fire(struct krt_proto *p) { byte buf[32768]; int l, seen_hdr; if (krt_scan_fd < 0) { krt_scan_fd = open("/proc/net/route", O_RDONLY); if (krt_scan_fd < 0) die("/proc/net/route: %m"); } else if (lseek(krt_scan_fd, 0, SEEK_SET) < 0) { log(L_ERR "krt seek: %m"); return; } seen_hdr = 0; while ((l = read(krt_scan_fd, buf, sizeof(buf))) > 0) { byte *z = buf; if (l & 127) { log(L_ERR "krt read: misaligned entry: l=%d", l); return; } while (l >= 128) { if (seen_hdr++) krt_parse_entry(z, p); z += 128; l -= 128; } } if (l < 0) { log(L_ERR "krt read: %m"); return; } DBG("KRT scan done, seen %d lines\n", seen_hdr); }