static int trie_node_same(struct f_trie_node *t1, struct f_trie_node *t2) { if ((t1 == NULL) && (t2 == NULL)) return 1; if ((t1 == NULL) || (t2 == NULL)) return 0; if ((t1->plen != t2->plen) || (! ipa_equal(t1->addr, t2->addr)) || (! ipa_equal(t1->accept, t2->accept))) return 0; return trie_node_same(t1->c[0], t2->c[0]) && trie_node_same(t1->c[1], t2->c[1]); }
static inline int olock_same(struct object_lock *x, struct object_lock *y) { return x->type == y->type && x->iface == y->iface && x->vrf == y->vrf && x->port == y->port && x->inst == y->inst && ipa_equal(x->addr, y->addr); }
/** * bgp_incoming_connection - handle an incoming connection * @sk: TCP socket * @dummy: unused * * This function serves as a socket hook for accepting of new BGP * connections. It searches a BGP instance corresponding to the peer * which has connected and if such an instance exists, it creates a * &bgp_conn structure, attaches it to the instance and either sends * an Open message or (if there already is an active connection) it * closes the new connection by sending a Notification message. */ static int bgp_incoming_connection(sock *sk, int dummy UNUSED) { struct proto_config *pc; DBG("BGP: Incoming connection from %I port %d\n", sk->daddr, sk->dport); WALK_LIST(pc, config->protos) if (pc->protocol == &proto_bgp && pc->proto) { struct bgp_proto *p = (struct bgp_proto *) pc->proto; if (ipa_equal(p->cf->remote_ip, sk->daddr) && (!ipa_has_link_scope(sk->daddr) || (p->cf->iface == sk->iface))) { /* We are in proper state and there is no other incoming connection */ int acc = (p->p.proto_state == PS_START || p->p.proto_state == PS_UP) && (p->start_state >= BSS_CONNECT) && (!p->incoming_conn.sk); if (p->conn && (p->conn->state == BS_ESTABLISHED) && p->gr_ready) { bgp_store_error(p, NULL, BE_MISC, BEM_GRACEFUL_RESTART); bgp_handle_graceful_restart(p); bgp_conn_enter_idle_state(p->conn); acc = 1; } BGP_TRACE(D_EVENTS, "Incoming connection from %I%J (port %d) %s", sk->daddr, ipa_has_link_scope(sk->daddr) ? sk->iface : NULL, sk->dport, acc ? "accepted" : "rejected"); if (!acc) goto reject; int hops = p->cf->multihop ? : 1; if (sk_set_ttl(sk, p->cf->ttl_security ? 255 : hops) < 0) goto err; if (p->cf->ttl_security) if (sk_set_min_ttl(sk, 256 - hops) < 0) goto err; bgp_setup_conn(p, &p->incoming_conn); bgp_setup_sk(&p->incoming_conn, sk); bgp_send_open(&p->incoming_conn); return 0; err: sk_log_error(sk, p->p.name); log(L_ERR "%s: Incoming connection aborted", p->p.name); rfree(sk); return 0; } }
/** * bgp_find_proto - find existing proto for incoming connection * @sk: TCP socket * */ static struct bgp_proto * bgp_find_proto(sock *sk) { struct proto_config *pc; WALK_LIST(pc, config->protos) if ((pc->protocol == &proto_bgp) && pc->proto) { struct bgp_proto *p = (struct bgp_proto *) pc->proto; if (ipa_equal(p->cf->remote_ip, sk->daddr) && (!ipa_is_link_local(sk->daddr) || (p->cf->iface == sk->iface))) return p; } return NULL; }
/** * bgp_incoming_connection - handle an incoming connection * @sk: TCP socket * @dummy: unused * * This function serves as a socket hook for accepting of new BGP * connections. It searches a BGP instance corresponding to the peer * which has connected and if such an instance exists, it creates a * &bgp_conn structure, attaches it to the instance and either sends * an Open message or (if there already is an active connection) it * closes the new connection by sending a Notification message. */ static int bgp_incoming_connection(sock *sk, int dummy UNUSED) { struct proto_config *pc; DBG("BGP: Incoming connection from %I port %d\n", sk->daddr, sk->dport); WALK_LIST(pc, config->protos) if (pc->protocol == &proto_bgp && pc->proto) { struct bgp_proto *p = (struct bgp_proto *) pc->proto; if (ipa_equal(p->cf->remote_ip, sk->daddr) && (!ipa_has_link_scope(sk->daddr) || (p->cf->iface == sk->iface))) { /* We are in proper state and there is no other incoming connection */ int acc = (p->p.proto_state == PS_START || p->p.proto_state == PS_UP) && (p->start_state >= BSS_CONNECT) && (!p->incoming_conn.sk); BGP_TRACE(D_EVENTS, "Incoming connection from %I%J (port %d) %s", sk->daddr, ipa_has_link_scope(sk->daddr) ? sk->iface : NULL, sk->dport, acc ? "accepted" : "rejected"); if (!acc) goto err; int hops = p->cf->multihop ? : 1; if (p->cf->ttl_security) { /* TTL security support */ if ((sk_set_ttl(sk, 255) < 0) || (sk_set_min_ttl(sk, 256 - hops) < 0)) { log(L_ERR "TTL security configuration failed, closing session"); goto err; } } else sk_set_ttl(sk, hops); bgp_setup_conn(p, &p->incoming_conn); bgp_setup_sk(&p->incoming_conn, sk); bgp_send_open(&p->incoming_conn); return 0; } }
static void scan_ifs(struct ifreq *r, int cnt) { struct iface i, *pi; struct ifa a; char *err, *colon; unsigned fl; ip_addr netmask; int l, scope; sockaddr *sa; if_start_update(); for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++) { int sec = 0; bzero(&i, sizeof(i)); bzero(&a, sizeof(a)); if (colon = strchr(r->ifr_name, ':')) { /* It's an alias -- let's interpret it as a secondary interface address */ sec = 1; *colon = 0; } strncpy(i.name, r->ifr_name, sizeof(i.name) - 1); if(ioctl(if_scan_sock, SIOCGIFADDR,r)<0) continue; get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.ip, NULL, 1); if (ipa_nonzero(a.ip)) { l = ipa_classify(a.ip); if (l < 0 || !(l & IADDR_HOST)) { log(L_ERR "%s: Invalid interface address", i.name); a.ip = IPA_NONE; } else { a.scope = l & IADDR_SCOPE_MASK; if (a.scope == SCOPE_HOST) i.flags |= IF_LOOPBACK | IF_IGNORE; } } if (ioctl(if_scan_sock, SIOCGIFFLAGS, r) < 0) { err = "SIOCGIFFLAGS"; faulty: log(L_ERR "%s(%s): %m", err, i.name); bad: i.flags = (i.flags & ~IF_LINK_UP) | IF_ADMIN_DOWN; continue; } fl = r->ifr_flags; if (fl & IFF_UP) i.flags |= IF_LINK_UP; if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0) { err = "SIOCGIFNETMASK"; goto faulty; } get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &netmask, NULL, 0); l = ipa_mklen(netmask); if (l < 0 || l == 31) { log(L_ERR "%s: Invalid netmask (%x)", i.name, netmask); goto bad; } a.pxlen = l; if (fl & IFF_POINTOPOINT) { a.flags |= IA_UNNUMBERED; if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0) { err = "SIOCGIFDSTADDR"; goto faulty; } get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL, 1); a.prefix = a.opposite; a.pxlen = BITS_PER_IP_ADDRESS; } else a.prefix = ipa_and(a.ip, ipa_mkmask(a.pxlen)); if (fl & IFF_LOOPBACK) i.flags |= IF_LOOPBACK | IF_IGNORE; if (1 #ifndef CONFIG_ALL_MULTICAST && (fl & IFF_MULTICAST) #endif #ifndef CONFIG_UNNUM_MULTICAST && !(a.flags & IA_UNNUMBERED) #endif ) i.flags |= IF_MULTICAST; scope = ipa_classify(a.ip); if (scope < 0) { log(L_ERR "%s: Invalid address", i.name); goto bad; } a.scope = scope & IADDR_SCOPE_MASK; if (a.pxlen < 32) { a.brd = ipa_or(a.prefix, ipa_not(ipa_mkmask(a.pxlen))); if (ipa_equal(a.ip, a.prefix) || ipa_equal(a.ip, a.brd)) { log(L_ERR "%s: Using network or broadcast address for interface", i.name); goto bad; } if (fl & IFF_BROADCAST) i.flags |= IF_BROADCAST; if (a.pxlen < 30) i.flags |= IF_MULTIACCESS; else a.opposite = ipa_opposite(a.ip, a.pxlen); } else a.brd = a.opposite; a.scope = SCOPE_UNIVERSE; if (ioctl(if_scan_sock, SIOCGIFMTU, r) < 0) { err = "SIOCGIFMTU"; goto faulty; } i.mtu = r->ifr_mtu; #ifdef SIOCGIFINDEX if (ioctl(if_scan_sock, SIOCGIFINDEX, r) >= 0) i.index = r->ifr_ifindex; else if (errno != EINVAL) DBG("SIOCGIFINDEX failed: %m\n"); else /* defined, but not supported by the kernel */ #endif /* * The kernel doesn't give us real ifindices, but we still need them * at least for OSPF unnumbered links. So let's make them up ourselves. */ if (pi = if_find_by_name(i.name)) i.index = pi->index; else { static int if_index_counter = 1; i.index = if_index_counter++; } pi = NULL; if (sec) { a.flags |= IA_SECONDARY; pi = if_find_by_index(i.index); } if (!pi) pi = if_update(&i); a.iface = pi; ifa_update(&a); } if_end_update(); }