Commit eb0f129f authored by Ondřej Zajíček's avatar Ondřej Zajíček

Merge branch 'socket2' into new

parents b1c030b0 48cff379
......@@ -36,8 +36,11 @@ typedef struct birdsock {
void (*err_hook)(struct birdsock *, int); /* errno or zero if EOF */
ip_addr faddr; /* For packet protocols: source of current packet */
unsigned fport;
/* Information about received datagrams (UDP, RAW), valid in rx_hook */
ip_addr faddr, laddr; /* src (From) and dst (Local) address of the datagram */
unsigned fport; /* src port of the datagram */
unsigned lifindex; /* local interface that received the datagram */
/* laddr and lifindex are valid only if SKF_LADDR_RX flag is set to request it */
int fd; /* System-dependent data */
node n;
......@@ -77,7 +80,9 @@ sk_send_buffer_empty(sock *sk)
/* Socket flags */
#define SKF_V6ONLY 1 /* Use IPV6_V6ONLY socket option */
#define SKF_V6ONLY 1 /* Use IPV6_V6ONLY socket option */
#define SKF_LADDR_RX 2 /* Report local address for RX packets */
#define SKF_LADDR_TX 4 /* Allow to specify local address for TX packets */
/*
......
......@@ -181,8 +181,8 @@ iface_patt_node_init:
iface_patt_node_body:
TEXT { this_ipn->pattern = $1; this_ipn->prefix = IPA_NONE; this_ipn->pxlen = 0; }
| prefix { this_ipn->pattern = NULL; this_ipn->prefix = $1.addr; this_ipn->pxlen = $1.len; }
| TEXT prefix { this_ipn->pattern = $1; this_ipn->prefix = $2.addr; this_ipn->pxlen = $2.len; }
| prefix_or_ipa { this_ipn->pattern = NULL; this_ipn->prefix = $1.addr; this_ipn->pxlen = $1.len; }
| TEXT prefix_or_ipa { this_ipn->pattern = $1; this_ipn->prefix = $2.addr; this_ipn->pxlen = $2.len; }
;
iface_negate:
......@@ -472,7 +472,7 @@ CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protoc
{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_OUT); } ;
CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging via BIRD logs]])
CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | events | packets }), [[Control protocol debugging via BIRD logs]])
CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | interfaces | events | packets }), [[Control protocol debugging via BIRD logs]])
{ proto_apply_cmd($2, proto_cmd_debug, 1, $3); } ;
CF_CLI_HELP(MRTDUMP, ..., [[Control protocol debugging via MRTdump files]])
......
......@@ -566,8 +566,8 @@ if_init(void)
* Interface Pattern Lists
*/
static int
iface_patt_match(struct iface_patt *ifp, struct iface *i)
int
iface_patt_match(struct iface_patt *ifp, struct iface *i, struct ifa *a)
{
struct iface_patt_node *p;
......@@ -588,23 +588,32 @@ iface_patt_match(struct iface_patt *ifp, struct iface *i)
continue;
}
if (p->pxlen)
if (!i->addr || !ipa_in_net(i->addr->ip, p->prefix, p->pxlen))
continue;
if (p->pxlen == 0)
return pos;
if (!a)
continue;
if (ipa_in_net(a->ip, p->prefix, p->pxlen))
return pos;
return pos;
if ((a->flags & IA_UNNUMBERED) &&
ipa_in_net(a->opposite, p->prefix, p->pxlen))
return pos;
continue;
}
return 0;
}
struct iface_patt *
iface_patt_find(list *l, struct iface *i)
iface_patt_find(list *l, struct iface *i, struct ifa *a)
{
struct iface_patt *p;
WALK_LIST(p, *l)
if (iface_patt_match(p, i))
if (iface_patt_match(p, i, a))
return p;
return NULL;
......
......@@ -83,6 +83,15 @@ struct iface *if_find_by_index(unsigned);
struct iface *if_find_by_name(char *);
void ifa_recalc_all_primary_addresses(void);
static inline int
ifa_match_addr(struct ifa *ifa, ip_addr addr)
{
if (ifa->flags & IA_UNNUMBERED)
return ipa_equal(addr, ifa->opposite);
else
return ipa_in_net(addr, ifa->prefix, ifa->pxlen);
}
/* The Neighbor Cache */
typedef struct neighbor {
......@@ -135,7 +144,8 @@ struct iface_patt {
/* Protocol-specific data follow after this structure */
};
struct iface_patt *iface_patt_find(list *, struct iface *);
int iface_patt_match(struct iface_patt *ifp, struct iface *i, struct ifa *a);
struct iface_patt *iface_patt_find(list *l, struct iface *i, struct ifa *a);
int iface_patts_equal(list *, list *, int (*)(struct iface_patt *, struct iface_patt *));
#endif
......@@ -30,7 +30,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
struct rt_dev_config *P = (void *) p->cf;
if (!EMPTY_LIST(P->iface_list) &&
!iface_patt_find(&P->iface_list, ad->iface))
!iface_patt_find(&P->iface_list, ad->iface, ad->iface->addr))
/* Empty list is automagically treated as "*" */
return;
......
......@@ -93,8 +93,8 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
{
case NEIGHBOR_EXSTART: /* Send empty packets */
n->myimms.bit.i = 1;
pkt = (struct ospf_dbdes_packet *) (ifa->sk->tbuf);
op = (struct ospf_packet *) pkt;
pkt = ospf_tx_buffer(ifa);
op = &pkt->ospf_packet;
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
pkt->iface_mtu = htons(ifa->iface->mtu);
pkt->options = hton_opt(oa->options);
......@@ -185,10 +185,10 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
}
/* Copy last sent packet again */
memcpy(ifa->sk->tbuf, n->ldbdes, length);
pkt = ospf_tx_buffer(ifa);
memcpy(pkt, n->ldbdes, length);
OSPF_PACKET(ospf_dump_dbdes, (struct ospf_dbdes_packet *) ifa->sk->tbuf,
"DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
ospf_send_to(ifa, n->ip);
if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint); /* Restart timer */
......
......@@ -47,7 +47,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
{
struct proto_ospf *po = ifa->oa->po;
struct proto *p = &po->proto;
char *beg = "Bad OSPF HELLO packet from ", *rec = " received: ";
char *beg = "OSPF: Bad HELLO packet from ";
unsigned int size, i, twoway, eligible, peers;
u32 tmp;
u32 *pnrid;
......@@ -55,7 +55,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
size = ntohs(ps_i->length);
if (size < sizeof(struct ospf_hello_packet))
{
log(L_ERR "%s%I - too short (%u B)", beg, faddr, size);
log(L_ERR "%s%I - too short (%u B)", beg, faddr, size);
return;
}
......@@ -67,38 +67,19 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
#ifdef OSPFv2
ip_addr mask = ps->netmask;
ipa_ntoh(mask);
if (ifa->type != OSPF_IT_VLINK)
{
char *msg = L_WARN "Received HELLO packet %s (%I) is inconsistent "
"with the primary address of interface %s.";
if ((ifa->type != OSPF_IT_PTP) &&
!ipa_equal(mask, ipa_mkmask(ifa->iface->addr->pxlen)))
{
if (!n) log(msg, "netmask", mask, ifa->iface->name);
return;
}
/* This check is not specified in RFC 2328, but it is needed
* to handle the case when there is more IP networks on one
* physical network (which is not handled in RFC 2328).
* We allow OSPF on primary IP address only and ignore HELLO packets
* with secondary addresses (which are sent for example by Quagga.
*/
if ((ifa->iface->addr->flags & IA_UNNUMBERED) ?
!ipa_equal(faddr, ifa->iface->addr->opposite) :
!ipa_equal(ipa_and(faddr,mask), ifa->iface->addr->prefix))
{
if (!n) log(msg, "address", faddr, ifa->iface->name);
return;
}
}
if ((ifa->type != OSPF_IT_VLINK) &&
(ifa->type != OSPF_IT_PTP) &&
!ipa_equal(mask, ipa_mkmask(ifa->addr->pxlen)))
{
log(L_ERR "%s%I - netmask mismatch (%I)", beg, faddr, mask);
return;
}
#endif
tmp = ntohs(ps->helloint);
if (tmp != ifa->helloint)
{
log(L_ERR "%s%I%shello interval mismatch (%d).", beg, faddr, rec, tmp);
log(L_ERR "%s%I - hello interval mismatch (%d)", beg, faddr, tmp);
return;
}
......@@ -109,14 +90,14 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
#endif
if (tmp != ifa->dead)
{
log(L_ERR "%s%I%sdead interval mismatch (%d).", beg, faddr, rec, tmp);
log(L_ERR "%s%I - dead interval mismatch (%d)", beg, faddr, tmp);
return;
}
tmp = !(ps->options & OPT_E);
if (tmp != ifa->oa->stub)
{
log(L_ERR "%s%I%sstub area flag mismatch (%d).", beg, faddr, rec, tmp);
log(L_ERR "%s%I - stub area flag mismatch (%d)", beg, faddr, tmp);
return;
}
......@@ -137,7 +118,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
}
if ((found == 0) && (ifa->strictnbma))
{
log(L_WARN "Ignoring new neighbor: %I on %s.", faddr,
log(L_WARN "Ignoring new neighbor: %I on %s", faddr,
ifa->iface->name);
return;
}
......@@ -153,7 +134,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
}
}
}
OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s.", faddr,
OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr,
ifa->iface->name);
n = ospf_neighbor_new(ifa);
......@@ -273,18 +254,18 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
return; /* Don't send any packet on stub iface */
p = (struct proto *) (ifa->oa->po);
DBG("%s: Hello/Poll timer fired on interface %s.\n",
p->name, ifa->iface->name);
DBG("%s: Hello/Poll timer fired on interface %s with IP %I\n",
p->name, ifa->iface->name, ifa->addr->ip);
/* Now we should send a hello packet */
pkt = (struct ospf_hello_packet *) (ifa->sk->tbuf);
op = (struct ospf_packet *) pkt;
pkt = ospf_tx_buffer(ifa);
op = &pkt->ospf_packet;
/* Now fill ospf_hello header */
ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
#ifdef OSPFv2
pkt->netmask = ipa_mkmask(ifa->iface->addr->pxlen);
pkt->netmask = ipa_mkmask(ifa->addr->pxlen);
ipa_hton(pkt->netmask);
if ((ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_PTP))
pkt->netmask = IPA_NONE;
......
This diff is collapsed.
......@@ -14,9 +14,10 @@ void ospf_iface_chstate(struct ospf_iface *ifa, u8 state);
void ospf_iface_sm(struct ospf_iface *ifa, int event);
struct ospf_iface *ospf_iface_find(struct proto_ospf *p, struct iface *what);
void ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface);
void ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a);
void ospf_iface_info(struct ospf_iface *ifa);
void ospf_iface_shutdown(struct ospf_iface *ifa);
void ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_config *ac, struct ospf_iface_patt *ip);
void ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ifa *addr, struct ospf_area_config *ac, struct ospf_iface_patt *ip);
void ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa);
void ospf_set_rxbuf_size(struct ospf_iface *ifa, u32 rxbuf);
......
......@@ -66,8 +66,8 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
if (EMPTY_LIST(n->ackl[queue]))
return;
pk = (struct ospf_lsack_packet *) ifa->sk->tbuf;
op = (struct ospf_packet *) ifa->sk->tbuf;
pk = ospf_tx_buffer(ifa);
op = &pk->ospf_packet;
ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
h = pk->lsh;
......@@ -92,8 +92,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
op->length = htons(len);
DBG("Sending and continuing! Len=%u\n", len);
OSPF_PACKET(ospf_dump_lsack, (struct ospf_lsack_packet *) ifa->sk->tbuf,
"LSACK packet sent via %s", ifa->iface->name);
OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->iface->name);
if (ifa->type == OSPF_IT_BCAST)
{
......@@ -120,8 +119,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
op->length = htons(len);
DBG("Sending! Len=%u\n", len);
OSPF_PACKET(ospf_dump_lsack, (struct ospf_lsack_packet *) ifa->sk->tbuf,
"LSACK packet sent via %s", ifa->iface->name);
OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->iface->name);
if (ifa->type == OSPF_IT_BCAST)
{
......
......@@ -44,8 +44,8 @@ ospf_lsreq_send(struct ospf_neighbor *n)
int i, j;
struct proto *p = &n->ifa->oa->po->proto;
pk = (struct ospf_lsreq_packet *) n->ifa->sk->tbuf;
op = (struct ospf_packet *) n->ifa->sk->tbuf;
pk = ospf_tx_buffer(n->ifa);
op = &pk->ospf_packet;
ospf_pkt_fill_hdr(n->ifa, pk, LSREQ_P);
......@@ -82,8 +82,7 @@ ospf_lsreq_send(struct ospf_neighbor *n)
i) * sizeof(struct ospf_lsreq_header);
op->length = htons(length);
OSPF_PACKET(ospf_dump_lsreq, (struct ospf_lsreq_packet *) n->ifa->sk->tbuf,
"LSREQ packet sent to %I via %s", n->ip, n->ifa->iface->name);
OSPF_PACKET(ospf_dump_lsreq, pk, "LSREQ packet sent to %I via %s", n->ip, n->ifa->iface->name);
ospf_send_to(n->ifa, n->ip);
}
......
......@@ -269,8 +269,8 @@ ospf_lsupd_flood(struct proto_ospf *po,
struct ospf_packet *op;
struct ospf_lsa_header *lh;
pk = (struct ospf_lsupd_packet *) ifa->sk->tbuf;
op = (struct ospf_packet *) ifa->sk->tbuf;
pk = ospf_tx_buffer(ifa);
op = &pk->ospf_packet;
ospf_pkt_fill_hdr(ifa, pk, LSUPD_P);
pk->lsano = htonl(1);
......@@ -303,8 +303,7 @@ ospf_lsupd_flood(struct proto_ospf *po,
op->length = htons(len);
OSPF_PACKET(ospf_dump_lsupd, (struct ospf_lsupd_packet *) ifa->sk->tbuf,
"LSUPD packet flooded via %s", ifa->iface->name);
OSPF_PACKET(ospf_dump_lsupd, pk, "LSUPD packet flooded via %s", ifa->iface->name);
switch (ifa->type)
{
......@@ -348,11 +347,11 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
if (EMPTY_LIST(*l))
return;
pk = (struct ospf_lsupd_packet *) n->ifa->sk->tbuf;
op = (struct ospf_packet *) n->ifa->sk->tbuf;
DBG("LSupd: 1st packet\n");
pk= ospf_tx_buffer(n->ifa);
op = &pk->ospf_packet;
ospf_pkt_fill_hdr(n->ifa, pk, LSUPD_P);
len = sizeof(struct ospf_lsupd_packet);
lsano = 0;
......@@ -373,8 +372,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
pk->lsano = htonl(lsano);
op->length = htons(len);
OSPF_PACKET(ospf_dump_lsupd, (struct ospf_lsupd_packet *) n->ifa->sk->tbuf,
"LSUPD packet sent to %I via %s", n->ip, n->ifa->iface->name);
OSPF_PACKET(ospf_dump_lsupd, pk, "LSUPD packet sent to %I via %s", n->ip, n->ifa->iface->name);
ospf_send_to(n->ifa, n->ip);
DBG("LSupd: next packet\n");
......@@ -395,8 +393,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
pk->lsano = htonl(lsano);
op->length = htons(len);
OSPF_PACKET(ospf_dump_lsupd, (struct ospf_lsupd_packet *) n->ifa->sk->tbuf,
"LSUPD packet sent to %I via %s", n->ip, n->ifa->iface->name);
OSPF_PACKET(ospf_dump_lsupd, pk, "LSUPD packet sent to %I via %s", n->ip, n->ifa->iface->name);
ospf_send_to(n->ifa, n->ip);
}
}
......@@ -414,7 +411,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
unsigned int size = ntohs(ps_i->length);
if (size < (sizeof(struct ospf_lsupd_packet) + sizeof(struct ospf_lsa_header)))
{
log(L_ERR "Bad OSPF LSUPD packet from %I - too short (%u B)", n->ip, size);
log(L_ERR "OSPF: Bad LSUPD packet from %I - too short (%u B)", n->ip, size);
return;
}
......@@ -535,7 +532,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
{
if (!nifa->iface)
continue;
if (ipa_equal(nifa->iface->addr->ip, ipa_from_u32(lsatmp.id)))
if (ipa_equal(nifa->addr->ip, ipa_from_u32(lsatmp.id)))
{
self = 1;
break;
......
......@@ -449,13 +449,12 @@ bdr_election(struct ospf_iface *ifa)
me.state = NEIGHBOR_2WAY;
me.rid = myid;
me.priority = ifa->priority;
me.ip = ifa->addr->ip;
#ifdef OSPFv2
me.ip = ifa->iface->addr->ip;
me.dr = ipa_to_u32(ifa->drip);
me.bdr = ipa_to_u32(ifa->bdrip);
#else /* OSPFv3 */
me.ip = ifa->lladdr;
me.dr = ifa->drid;
me.bdr = ifa->bdrid;
me.iface_id = ifa->iface->index;
......
......@@ -42,6 +42,32 @@
* and deletion. Each LSA is kept in two pieces: header and body. Both of them are
* kept in the endianity of the CPU.
*
* In OSPFv2 specification, it is implied that there is one IP prefix
* for each physical network/interface (unless it is an ptp link). But
* in modern systems, there might be more independent IP prefixes
* associated with an interface. To handle this situation, we have
* one &ospf_iface for each active IP prefix (instead for each active
* iface); This behaves like virtual interface for the purpose of OSPF.
* If we receive packet, we associate it with a proper virtual interface
* mainly according to its source address.
*
* OSPF keeps one socket per &ospf_iface. This allows us (compared to
* one socket approach) to evade problems with a limit of multicast
* groups per socket and with sending multicast packets to appropriate
* interface in a portable way. The socket is associated with
* underlying physical iface and should not receive packets received
* on other ifaces (unfortunately, this is not true on
* BSD). Generally, one packet can be received by more sockets (for
* example, if there are more &ospf_iface on one physical iface),
* therefore we explicitly filter received packets according to
* src/dst IP address and received iface.
*
* Vlinks are implemented using particularly degenerate form of
* &ospf_iface, which has several exceptions: it does not have its
* iface or socket (it copies these from 'parent' &ospf_iface) and it
* is present in iface list even when down (it is not freed in
* ospf_iface_down()).
*
* The heart beat of ospf is ospf_disp(). It is called at regular intervals
* (&proto_ospf->tick). It is responsible for aging and flushing of LSAs in
* the database, for routing table calculaction and it call area_disp() of every
......@@ -79,7 +105,6 @@
static int ospf_reload_routes(struct proto *p);
static void ospf_rt_notify(struct proto *p, struct rtable *table UNUSED, net * n, rte * new, rte * old UNUSED, ea_list * attrs);
static void ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a);
static int ospf_rte_better(struct rte *new, struct rte *old);
static int ospf_rte_same(struct rte *new, struct rte *old);
static void ospf_disp(timer *timer);
......@@ -196,7 +221,7 @@ ospf_start(struct proto *p)
oa->options = OPT_R | OPT_E | OPT_V6;
#endif
}
ospf_iface_new(po, NULL, ac, ipatt);
ospf_iface_new(po, NULL, NULL, ac, ipatt);
}
}
}
......@@ -480,7 +505,9 @@ ospf_shutdown(struct proto *p)
OSPF_TRACE(D_EVENTS, "Shutdown requested");
/* And send to all my neighbors 1WAY */
WALK_LIST(ifa, po->iface_list) ospf_iface_shutdown(ifa);
WALK_LIST(ifa, po->iface_list)
if (ifa->state > OSPF_IS_DOWN)
ospf_iface_shutdown(ifa);
return PS_DOWN;
}
......@@ -501,27 +528,6 @@ ospf_rt_notify(struct proto *p, rtable *tbl UNUSED, net * n, rte * new, rte * ol
flush_ext_lsa(n, po);
}
static void
ospf_ifa_notify(struct proto *p, unsigned flags UNUSED, struct ifa *a)
{
struct proto_ospf *po = (struct proto_ospf *) p;
struct ospf_iface *ifa;
if ((a->flags & IA_SECONDARY) || (a->flags & IA_UNNUMBERED))
return;
WALK_LIST(ifa, po->iface_list)
{
if (ifa->iface == a->iface)
{
schedule_rt_lsa(ifa->oa);
/* Event 5 from RFC5340 4.4.3. */
schedule_link_lsa(ifa);
return;
}
}
}
static void
ospf_get_status(struct proto *p, byte * buf)
{
......@@ -712,12 +718,17 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
WALK_LIST(ifa, po->iface_list)
{
/* FIXME: better handling of vlinks */
if (ifa->iface == NULL)
continue;
/* FIXME: better matching of interface_id in OSPFv3 */
if (oldip = (struct ospf_iface_patt *)
iface_patt_find(&oldac->patt_list, ifa->iface))
iface_patt_find(&oldac->patt_list, ifa->iface, ifa->addr))
{
/* Now reconfigure interface */
if (!(newip = (struct ospf_iface_patt *)
iface_patt_find(&newac->patt_list, ifa->iface)))
iface_patt_find(&newac->patt_list, ifa->iface, ifa->addr)))
return 0;
/* HELLO TIMER */
......@@ -778,18 +789,17 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
}
/* stub */
if ((oldip->stub == 0) && (newip->stub != 0))
int old_stub = ospf_iface_stubby(oldip, ifa->addr);
int new_stub = ospf_iface_stubby(newip, ifa->addr);
if (!old_stub && new_stub)
{
ifa->stub = newip->stub;
ifa->stub = 1;
OSPF_TRACE(D_EVENTS, "Interface %s is now stub.", ifa->iface->name);
}
if ((oldip->stub != 0) && (newip->stub == 0) &&
((ifa->ioprob & OSPF_I_IP) == 0) &&
(((ifa->ioprob & OSPF_I_MC) == 0) || (ifa->type == OSPF_IT_NBMA)))
if (old_stub && !new_stub && (ifa->ioprob == OSPF_I_OK))
{
ifa->stub = newip->stub;
OSPF_TRACE(D_EVENTS,
"Interface %s is no longer stub.", ifa->iface->name);
ifa->stub = 0;
OSPF_TRACE(D_EVENTS, "Interface %s is no longer stub.", ifa->iface->name);
}
#ifdef OSPFv2
......@@ -1209,7 +1219,7 @@ show_lsa_sum_net(struct top_hash_entry *he)
lsa_get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts, &rest);
#endif
cli_msg(-1016, "\t\txnetwork %I/%d", ip, pxlen);
cli_msg(-1016, "\t\txnetwork %I/%d metric %u", ip, pxlen, ls->metric);
}
static inline void
......@@ -1218,7 +1228,7 @@ show_lsa_sum_rt(struct top_hash_entry *he)
u32 dst_rid, options;
#ifdef OSPFv2
// struct ospf_lsa_sum *ls = he->lsa_body;
struct ospf_lsa_sum *ls = he->lsa_body;
dst_rid = he->lsa.id;
options = 0;
#else /* OSPFv3 */
......@@ -1227,7 +1237,7 @@ show_lsa_sum_rt(struct top_hash_entry *he)
options = ls->options & OPTIONS_MASK;
#endif
cli_msg(-1016, "\t\txrouter %R", dst_rid);
cli_msg(-1016, "\t\txrouter %R metric %u", dst_rid, ls->metric);
}
......
......@@ -159,6 +159,7 @@ struct ospf_iface
{
node n;
struct iface *iface; /* Nest's iface */
struct ifa *addr; /* IP prefix associated with that OSPF iface */
struct ospf_area *oa;
struct object_lock *lock;
sock *sk; /* IP socket (for DD ...) */
......@@ -170,7 +171,8 @@ struct ospf_iface
u32 dead; /* after "deadint" missing hellos is router dead */
u32 vid; /* Id of peer of virtual link */
ip_addr vip; /* IP of peer of virtual link */
struct ospf_area *voa; /* Area wich the vlink goes through */
struct ospf_iface *vifa; /* OSPF iface which the vlink goes through */
struct ospf_area *voa; /* OSPF area which the vlink goes through */
u16 inftransdelay; /* The estimated number of seconds it takes to
transmit a Link State Update Packet over this
interface. LSAs contained in the update */
......@@ -192,7 +194,6 @@ struct ospf_iface
u32 dr_iface_id; /* if drid is valid, this is iface_id of DR (for connecting network) */
u8 instance_id; /* Used to differentiate between more OSPF
instances on one interface */
ip_addr lladdr; /* Used link-local addr */
#endif
u8 type; /* OSPF view of type */
......@@ -203,9 +204,6 @@ struct ospf_iface
#define OSPF_IT_UNDEF 4
u8 strictnbma; /* Can I talk with unknown neighbors? */
u8 stub; /* Inactive interface */
#define OSPF_I_OK 0 /* Everything OK */
#define OSPF_I_MC 1 /* I didn't open MC socket */
#define OSPF_I_IP 2 /* I didn't open IP socet */
u8 state; /* Interface state machine */
#define OSPF_IS_DOWN 0 /* Not working */
#define OSPF_IS_LOOP 1 /* Should never happen */
......@@ -237,9 +235,13 @@ struct ospf_iface
#endif
int fadj; /* Number of full adjacent neigh */
list nbma_list;
u8 priority; /* A router priority for DR election */
u8 priority; /* A router priority for DR election */
u8 ioprob;
u8 dr_up; /* Socket is a member of DRouters group */
#define OSPF_I_OK 0 /* Everything OK */
#define OSPF_I_SK 1 /* Socket open failed */
#define OSPF_I_LL 2 /* Missing link-local address (OSPFv3) */
u8 sk_spf; /* Socket is a member of SPFRouters group */
u8 sk_dr; /* Socket is a member of DRouters group */
u32 rxbuf;
};
......@@ -675,8 +677,8 @@ struct ospf_neighbor
#define ISM_WAITF 1 /* Wait timer fired */
#define ISM_BACKS 2 /* Backup seen */
#define ISM_NEICH 3 /* Neighbor change */
#define ISM_LOOP 4 /* Loop indicated */
#define ISM_UNLOOP 5 /* Unloop indicated */
// #define ISM_LOOP 4 /* Loop indicated */
// #define ISM_UNLOOP 5 /* Unloop indicated */
#define ISM_DOWN 6 /* Interface down */
/* Definitions for neighbor state machine */
......@@ -770,6 +772,25 @@ struct ospf_iface_patt
#endif
};
#if defined(OSPFv2) && !defined(CONFIG_MC_PROPER_SRC)
static inline int
ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr)
{
/*
* We cannot properly support multiple OSPF ifaces on real iface
* with multiple prefixes, therefore we force OSPF ifaces with
* non-primary IP prefixes to be stub.
*/
return ip->stub || !(addr->flags & IA_PRIMARY);
}
#else
static inline int
ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr UNUSED)
{
return ip->stub;
}
#endif
int ospf_import_control(struct proto *p, rte **new, ea_list **attrs,
struct linpool *pool);
struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
......
......@@ -140,13 +140,6 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
return 0;
}
if (n && (ifa != n->ifa))
{
OSPF_TRACE(D_PACKETS, "OSPF_auth: received packet from strange interface (%s/%s)",
ifa->iface->name, n->ifa->iface->name);
return 0;
}
switch(ifa->autype)
{
case OSPF_AUTH_NONE:
......@@ -178,19 +171,13 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
return 0;
}
if (ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE != size)
if (ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE > size)
{
OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch (%d vs %d)",
ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE, size);
return 0;
}
if (pkt->u.md5.zero)
{
OSPF_TRACE(D_PACKETS, "OSPF_auth: \"zero\" area is non-zero");
return 0;
}
tail = ((void *)pkt) + ntohs(pkt->length);
if (ifa->passwords)
......@@ -251,12 +238,13 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
static int
ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size)
{ return 1; }
#endif
/**
* ospf_rx_hook
* @sk: socket we received the packet. Its ignored.
* @sk: socket we received the packet.
* @size: size of the packet
*
* This is the entry point for messages from neighbors. Many checks (like
......@@ -264,21 +252,52 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
* non generic functions.
*/
int
ospf_rx_hook(sock * sk, int size)
ospf_rx_hook(sock *sk, int size)