Commit 70945cb6 authored by Ondřej Zajíček's avatar Ondřej Zajíček
Browse files

Temporary integrated OSPF commit.

parent 9eceab33
......@@ -2332,6 +2332,7 @@ protocol ospf <name> {
tx length <num>;
type [broadcast|bcast|pointopoint|ptp|
nonbroadcast|nbma|pointomultipoint|ptmp];
link lsa suppression <switch>;
strict nonbroadcast <switch>;
real broadcast <switch>;
ptp netmask <switch>;
......@@ -2596,9 +2597,16 @@ protocol ospf <name> {
communication, or if the NBMA network is used as an (possibly
unnumbered) PtP link.
<tag>strict nonbroadcast <M>switch</M></tag>
<tag>link lsa suppression <m/switch/</tag>
In OSPFv3, link LSAs are generated for each link, announcing link-local
IPv6 address of the router to its local neighbors. These are useless on
PtP or PtMP networks and this option allows to suppress the link LSA
origination for such interfaces. The option is ignored on other than PtP
or PtMP interfaces. Default value is no.
<tag>strict nonbroadcast <m/switch/</tag>
If set, don't send hello to any undefined neighbor. This switch is
ignored on other than NBMA or PtMP networks. Default value is no.
ignored on other than NBMA or PtMP interfaces. Default value is no.
<tag>real broadcast <m/switch/</tag>
In <cf/type broadcast/ or <cf/type ptp/ network configuration, OSPF
......
......@@ -33,6 +33,12 @@
#define ABS(a) ((a)>=0 ? (a) : -(a))
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
#define BIT32_VAL(p) (((u32) 1) << ((p) % 32))
#define BIT32_TEST(b,p) ((b)[(p)/32] & BIT32_VAL(p))
#define BIT32_SET(b,p) ((b)[(p)/32] |= BIT32_VAL(p))
#define BIT32_CLR(b,p) ((b)[(p)/32] &= ~BIT32_VAL(p))
#define BIT32_ZERO(b,l) memset((b), 0, (l)/8)
#ifndef NULL
#define NULL ((void *) 0)
#endif
......
......@@ -68,10 +68,12 @@ typedef struct siterator {
#define SNODE (snode *)
#define SHEAD(list) ((void *)((list).head))
#define STAIL(list) ((void *)((list).tail))
#define WALK_SLIST(n,list) for(n=SHEAD(list);(SNODE (n))->next; \
n=(void *)((SNODE (n))->next))
#define SNODE_NEXT(n) ((void *)((SNODE (n))->next))
#define SNODE_VALID(n) ((SNODE (n))->next)
#define WALK_SLIST(n,list) for(n=SHEAD(list); SNODE_VALID(n); n=SNODE_NEXT(n))
#define WALK_SLIST_DELSAFE(n,nxt,list) \
for(n=SHEAD(list); nxt=(void *)((SNODE (n))->next); n=(void *) nxt)
for(n=SHEAD(list); nxt=SNODE_NEXT(n); n=(void *) nxt)
#define EMPTY_SLIST(list) (!(list).head->next)
void s_add_tail(slist *, snode *);
......
......@@ -21,7 +21,9 @@ static list *this_nets;
static struct area_net_config *this_pref;
static struct ospf_stubnet_config *this_stubnet;
#ifdef OSPFv2
static inline int ospf_cfg_is_v2(void) { return OSPF_CFG->ospf2; }
static inline int ospf_cfg_is_v3(void) { return ! OSPF_CFG->ospf2; }
static void
ospf_iface_finish(void)
{
......@@ -38,21 +40,6 @@ ospf_iface_finish(void)
if ((ip->autype == OSPF_AUTH_NONE) && (ip->passwords != NULL))
log(L_WARN "Password option without authentication option does not make sense");
}
#endif
#ifdef OSPFv3
static void
ospf_iface_finish(void)
{
struct ospf_iface_patt *ip = OSPF_PATT;
if (ip->deadint == 0)
ip->deadint = ip->deadc * ip->helloint;
if ((ip->autype != OSPF_AUTH_NONE) || (get_passwords() != NULL))
cf_error("Authentication not supported in OSPFv3");
}
#endif
static void
ospf_area_finish(void)
......@@ -61,12 +48,12 @@ ospf_area_finish(void)
cf_error("Backbone area cannot be stub/NSSA");
if (this_area->summary && (this_area->type == OPT_E))
cf_error("Only Stub/NSSA areas can use summary propagation");
cf_error("Only stub/NSSA areas can use summary propagation");
if (this_area->default_nssa && ((this_area->type != OPT_N) || ! this_area->summary))
cf_error("Only NSSA areas with summary propagation can use NSSA default route");
if ((this_area->default_cost & LSA_EXT_EBIT) && ! this_area->default_nssa)
if ((this_area->default_cost & LSA_EXT3_EBIT) && ! this_area->default_nssa)
cf_error("Only NSSA default route can use type 2 metric");
}
......@@ -80,15 +67,22 @@ ospf_proto_finish(void)
int areano = 0;
int backbone = 0;
int nssa = 0;
struct ospf_area_config *ac;
WALK_LIST(ac, cf->area_list)
{
areano++;
if (ac->areaid == 0)
backbone = 1;
backbone = 1;
if (ac->type == OPT_N)
nssa = 1;
}
cf->abr = areano > 1;
/* Route export or NSSA translation (RFC 3101 3.1) */
cf->asbr = (this_proto->out_filter != FILTER_REJECT) || (nssa && cf->abr);
if (cf->abr && !backbone)
{
struct ospf_area_config *ac = cfg_allocz(sizeof(struct ospf_area_config));
......@@ -101,26 +95,27 @@ ospf_proto_finish(void)
}
if (!cf->abr && !EMPTY_LIST(cf->vlink_list))
cf_error( "Vlinks cannot be used on single area router");
cf_error("Vlinks cannot be used on single area router");
if (cf->asbr && (areano == 1) && (this_area->type == 0))
cf_error("ASBR must be in non-stub area");
}
static inline void
check_defcost(int cost)
ospf_check_defcost(int cost)
{
if ((cost <= 0) || (cost >= LSINFINITY))
cf_error("Default cost must be in range 1-%d", LSINFINITY-1);
}
static inline void
set_instance_id(unsigned id)
ospf_check_auth(void)
{
#ifdef OSPFv3
OSPF_PATT->instance_id = id;
#else
cf_error("Instance ID requires OSPFv3");
#endif
if (ospf_cfg_is_v3())
cf_error("Authentication not supported in OSPFv3");
}
CF_DECLS
CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF_ROUTER_ID)
......@@ -132,7 +127,7 @@ CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK, ONLY, BFD)
CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY, LENGTH)
CF_KEYWORDS(SECONDARY, MERGE)
CF_KEYWORDS(SECONDARY, MERGE, LSA, SUPPRESSION)
%type <t> opttext
%type <ld> lsadb_args
......@@ -146,8 +141,8 @@ ospf_proto_start: proto_start OSPF {
this_proto = proto_config_new(&proto_ospf, sizeof(struct ospf_config), $1);
init_list(&OSPF_CFG->area_list);
init_list(&OSPF_CFG->vlink_list);
OSPF_CFG->rfc1583 = DEFAULT_RFC1583;
OSPF_CFG->tick = DEFAULT_OSPFTICK;
OSPF_CFG->tick = OSPF_DEFAULT_TICK;
OSPF_CFG->ospf2 = OSPF_IS_V2;
}
;
......@@ -160,7 +155,7 @@ ospf_proto_item:
proto_item
| RFC1583COMPAT bool { OSPF_CFG->rfc1583 = $2; }
| STUB ROUTER bool { OSPF_CFG->stub_router = $3; }
| ECMP bool { OSPF_CFG->ecmp = $2 ? DEFAULT_ECMP_LIMIT : 0; }
| ECMP bool { OSPF_CFG->ecmp = $2 ? OSPF_DEFAULT_ECMP_LIMIT : 0; }
| ECMP bool LIMIT expr { OSPF_CFG->ecmp = $2 ? $4 : 0; if ($4 < 0) cf_error("ECMP limit cannot be negative"); }
| MERGE EXTERNAL bool { OSPF_CFG->merge_external = $3; }
| TICK expr { OSPF_CFG->tick = $2; if($2<=0) cf_error("Tick must be greater than zero"); }
......@@ -171,9 +166,9 @@ ospf_area_start: AREA idval {
this_area = cfg_allocz(sizeof(struct ospf_area_config));
add_tail(&OSPF_CFG->area_list, NODE this_area);
this_area->areaid = $2;
this_area->default_cost = DEFAULT_STUB_COST;
this_area->default_cost = OSPF_DEFAULT_STUB_COST;
this_area->type = OPT_E;
this_area->transint = DEFAULT_TRANSINT;
this_area->transint = OSPF_DEFAULT_TRANSINT;
init_list(&this_area->patt_list);
init_list(&this_area->net_list);
......@@ -195,9 +190,9 @@ ospf_area_item:
| NSSA { this_area->type = OPT_N; }
| SUMMARY bool { this_area->summary = $2; }
| DEFAULT NSSA bool { this_area->default_nssa = $3; }
| DEFAULT COST expr { this_area->default_cost = $3; check_defcost($3); }
| DEFAULT COST2 expr { this_area->default_cost = $3 | LSA_EXT_EBIT; check_defcost($3); }
| STUB COST expr { this_area->default_cost = $3; check_defcost($3); }
| DEFAULT COST expr { this_area->default_cost = $3; ospf_check_defcost($3); }
| DEFAULT COST2 expr { this_area->default_cost = $3 | LSA_EXT3_EBIT; ospf_check_defcost($3); }
| STUB COST expr { this_area->default_cost = $3; ospf_check_defcost($3); }
| TRANSLATOR bool { this_area->translator = $2; }
| TRANSLATOR STABILITY expr { this_area->transint = $3; }
| NETWORKS { this_nets = &this_area->net_list; } '{' pref_list '}'
......@@ -249,10 +244,10 @@ ospf_vlink_item:
| WAIT expr { OSPF_PATT->waitint = $2 ; }
| DEAD expr { OSPF_PATT->deadint = $2 ; if ($2<=1) cf_error("Dead interval must be greater than one"); }
| DEAD COUNT expr { OSPF_PATT->deadc = $3 ; if ($3<=1) cf_error("Dead count must be greater than one"); }
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; }
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; }
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; }
| password_list
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE; }
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE; ospf_check_auth(); }
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT; ospf_check_auth(); }
| password_list { ospf_check_auth(); }
;
ospf_vlink_start: VIRTUAL LINK idval
......@@ -292,18 +287,19 @@ ospf_iface_item:
| TYPE PTP { OSPF_PATT->type = OSPF_IT_PTP ; }
| TYPE POINTOMULTIPOINT { OSPF_PATT->type = OSPF_IT_PTMP ; }
| TYPE PTMP { OSPF_PATT->type = OSPF_IT_PTMP ; }
| REAL BROADCAST bool { OSPF_PATT->real_bcast = $3; if (OSPF_VERSION != 2) cf_error("Real broadcast option requires OSPFv2"); }
| PTP NETMASK bool { OSPF_PATT->ptp_netmask = $3; if (OSPF_VERSION != 2) cf_error("Real netmask option requires OSPFv2"); }
| REAL BROADCAST bool { OSPF_PATT->real_bcast = $3; if (!ospf_cfg_is_v2()) cf_error("Real broadcast option requires OSPFv2"); }
| PTP NETMASK bool { OSPF_PATT->ptp_netmask = $3; if (!ospf_cfg_is_v2()) cf_error("PtP netmask option requires OSPFv2"); }
| TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); }
| PRIORITY expr { OSPF_PATT->priority = $2 ; if (($2<0) || ($2>255)) cf_error("Priority must be in range 0-255"); }
| STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
| STUB bool { OSPF_PATT->stub = $2 ; }
| CHECK LINK bool { OSPF_PATT->check_link = $3; }
| ECMP WEIGHT expr { OSPF_PATT->ecmp_weight = $3 - 1; if (($3<1) || ($3>256)) cf_error("ECMP weight must be in range 1-256"); }
| LINK LSA SUPPRESSION bool { OSPF_PATT->link_lsa_suppression = $4; if (!ospf_cfg_is_v3()) cf_error("Link LSA suppression option requires OSPFv3"); }
| NEIGHBORS '{' nbma_list '}'
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; }
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; }
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; }
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE; }
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE; ospf_check_auth(); }
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT; ospf_check_auth(); }
| RX BUFFER NORMAL { OSPF_PATT->rx_buffer = 0; }
| RX BUFFER LARGE { OSPF_PATT->rx_buffer = OSPF_MAX_PKT_SIZE; }
| RX BUFFER expr { OSPF_PATT->rx_buffer = $3; if (($3 < OSPF_MIN_PKT_SIZE) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("Buffer size must be in range 256-65535"); }
......@@ -314,7 +310,7 @@ ospf_iface_item:
| TTL SECURITY TX ONLY { OSPF_PATT->ttl_security = 2; }
| BFD bool { OSPF_PATT->bfd = $2; cf_check_bfd($2); }
| SECONDARY bool { OSPF_PATT->bsd_secondary = $2; }
| password_list
| password_list { ospf_check_auth(); }
;
pref_list:
......@@ -349,7 +345,7 @@ nbma_eligible:
| ELIGIBLE { $$ = 1; }
;
nbma_item: IPA nbma_eligible ';'
nbma_item: ipa nbma_eligible ';'
{
this_nbma = cfg_allocz(sizeof(struct nbma_node));
add_tail(&OSPF_PATT->nbma_list, NODE this_nbma);
......@@ -384,11 +380,11 @@ ospf_iface_start:
ospf_instance_id:
/* empty */
| INSTANCE expr { set_instance_id($2); }
| INSTANCE expr { OSPF_PATT->instance_id = $2; }
;
ospf_iface_patt_list:
iface_patt_list { if (OSPF_VERSION == 3) iface_patt_check(); } ospf_instance_id
iface_patt_list { if (ospf_cfg_is_v3()) iface_patt_check(); } ospf_instance_id
;
ospf_iface_opts:
......
This diff is collapsed.
/*
* BIRD -- OSPF
*
* (c) 1999 - 2004 Ondrej Filip <feela@network.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*
*/
#ifndef _BIRD_OSPF_DBDES_H_
#define _BIRD_OSPF_DBDES_H_
void ospf_dbdes_send(struct ospf_neighbor *n, int next);
void ospf_dbdes_receive(struct ospf_packet *ps, struct ospf_iface *ifa,
struct ospf_neighbor *n);
#endif /* _BIRD_OSPF_DBDES_H_ */
......@@ -2,6 +2,8 @@
* BIRD -- OSPF
*
* (c) 1999--2004 Ondrej Filip <feela@network.cz>
* (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
* (c) 2009--2014 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
......@@ -9,25 +11,26 @@
#include "ospf.h"
#ifdef OSPFv2
struct ospf_hello_packet
struct ospf_hello2_packet
{
struct ospf_packet ospf_packet;
ip_addr netmask;
struct ospf_packet hdr;
union ospf_auth auth;
u32 netmask;
u16 helloint;
u8 options;
u8 priority;
u32 deadint;
u32 dr;
u32 bdr;
};
#endif
u32 neighbors[];
};
#ifdef OSPFv3
struct ospf_hello_packet
struct ospf_hello3_packet
{
struct ospf_packet ospf_packet;
struct ospf_packet hdr;
u32 iface_id;
u8 priority;
u8 options3;
......@@ -37,286 +40,92 @@ struct ospf_hello_packet
u16 deadint;
u32 dr;
u32 bdr;
};
#endif
void
ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
struct ospf_neighbor *n, ip_addr faddr)
{
struct proto_ospf *po = ifa->oa->po;
struct proto *p = &po->proto;
char *beg = "OSPF: Bad HELLO packet from ";
unsigned int size, i, twoway, peers;
u32 tmp;
u32 *pnrid;
size = ntohs(ps_i->length);
if (size < sizeof(struct ospf_hello_packet))
{
log(L_ERR "%s%I - too short (%u B)", beg, faddr, size);
return;
}
struct ospf_hello_packet *ps = (void *) ps_i;
OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s", faddr, ifa->ifname);
#ifdef OSPFv2
ip_addr mask = ps->netmask;
ipa_ntoh(mask);
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 - hello interval mismatch (%d)", beg, faddr, tmp);
return;
}
#ifdef OSPFv2
tmp = ntohl(ps->deadint);
#else /* OSPFv3 */
tmp = ntohs(ps->deadint);
#endif
if (tmp != ifa->deadint)
{
log(L_ERR "%s%I - dead interval mismatch (%d)", beg, faddr, tmp);
return;
}
/* Check whether bits E, N match */
if ((ps->options ^ ifa->oa->options) & (OPT_E | OPT_N))
{
log(L_ERR "%s%I - area type mismatch (%x)", beg, faddr, ps->options);
return;
}
#ifdef OSPFv2
if (n && (n->rid != ntohl(ps_i->routerid)))
{
OSPF_TRACE(D_EVENTS,
"Neighbor %I has changed router id from %R to %R.",
n->ip, n->rid, ntohl(ps_i->routerid));
ospf_neigh_remove(n);
n = NULL;
}
#endif
if (!n)
{
if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
{
struct nbma_node *nn = find_nbma_node(ifa, faddr);
if (!nn && ifa->strictnbma)
{
log(L_WARN "Ignoring new neighbor: %I on %s", faddr, ifa->ifname);
return;
}
if (nn && (ifa->type == OSPF_IT_NBMA) &&
(((ps->priority == 0) && nn->eligible) ||
((ps->priority > 0) && !nn->eligible)))
{
log(L_ERR "Eligibility mismatch for neighbor: %I on %s", faddr, ifa->ifname);
return;
}
if (nn)
nn->found = 1;
}
OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr, ifa->ifname);
n = ospf_neighbor_new(ifa);
n->rid = ntohl(ps_i->routerid);
n->ip = faddr;
n->dr = ntohl(ps->dr);
n->bdr = ntohl(ps->bdr);
n->priority = ps->priority;
#ifdef OSPFv3
n->iface_id = ntohl(ps->iface_id);
#endif
if (n->ifa->cf->bfd)
ospf_neigh_update_bfd(n, n->ifa->bfd);
}
#ifdef OSPFv3 /* NOTE: this could also be relevant for OSPFv2 on PtP ifaces */
else if (!ipa_equal(faddr, n->ip))
{
OSPF_TRACE(D_EVENTS, "Neighbor address changed from %I to %I", n->ip, faddr);
n->ip = faddr;
}
#endif
ospf_neigh_sm(n, INM_HELLOREC);
pnrid = (u32 *) ((struct ospf_hello_packet *) (ps + 1));
peers = (size - sizeof(struct ospf_hello_packet))/ sizeof(u32);
twoway = 0;
for (i = 0; i < peers; i++)
{
if (ntohl(pnrid[i]) == po->router_id)
{
DBG("%s: Twoway received from %I\n", p->name, faddr);
ospf_neigh_sm(n, INM_2WAYREC);
twoway = 1;
break;
}
}
if (!twoway)
ospf_neigh_sm(n, INM_1WAYREC);
u32 olddr = n->dr;
u32 oldbdr = n->bdr;
u32 oldpriority = n->priority;
#ifdef OSPFv3
u32 oldiface_id = n->iface_id;
#endif
n->dr = ntohl(ps->dr);
n->bdr = ntohl(ps->bdr);
n->priority = ps->priority;
#ifdef OSPFv3
n->iface_id = ntohl(ps->iface_id);
#endif
u32 neighbors[];
};
/* Check priority change */
if (n->state >= NEIGHBOR_2WAY)
{
#ifdef OSPFv2
u32 neigh = ipa_to_u32(n->ip);
#else /* OSPFv3 */
u32 neigh = n->rid;
#endif
if (n->priority != oldpriority)
ospf_iface_sm(ifa, ISM_NEICH);
#ifdef OSPFv3
if (n->iface_id != oldiface_id)
ospf_iface_sm(ifa, ISM_NEICH);
#endif
/* Neighbor is declaring itself ad DR and there is no BDR */
if ((n->dr == neigh) && (n->bdr == 0)
&& (n->state != NEIGHBOR_FULL))
ospf_iface_sm(ifa, ISM_BACKS);
/* Neighbor is declaring itself as BDR */
if ((n->bdr == neigh) && (n->state != NEIGHBOR_FULL))
ospf_iface_sm(ifa, ISM_BACKS);
/* Neighbor is newly declaring itself as DR or BDR */
if (((n->dr == neigh) && (n->dr != olddr))
|| ((n->bdr == neigh) && (n->bdr != oldbdr)))
ospf_iface_sm(ifa, ISM_NEICH);
/* Neighbor is no more declaring itself as DR or BDR */
if (((olddr == neigh) && (n->dr != olddr))
|| ((oldbdr == neigh) && (n->bdr != oldbdr)))
ospf_iface_sm(ifa, ISM_NEICH);
}
if (ifa->type == OSPF_IT_NBMA)
{
if ((ifa->priority == 0) && (n->priority > 0))
ospf_hello_send(n->ifa, OHS_HELLO, n);
}
ospf_neigh_sm(n, INM_HELLOREC);
}
void
ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
{
struct ospf_hello_packet *pkt;
struct ospf_packet *op;
struct proto *p;
struct ospf_proto *p = ifa->oa->po;
struct ospf_packet *pkt;
struct ospf_neighbor *neigh, *n1;
u16 length;
int i;
struct nbma_node *nb;
u32 *neighbors;
uint length;
int i, max;
if (ifa->state <= OSPF_IS_LOOP)
return;
if (ifa->stub)
return; /* Don't send any packet on stub iface */
return;
p = (struct proto *) (ifa->oa->po);
DBG("%s: Hello/Poll timer fired on interface %s with IP %I\n",
p->name, ifa->ifname, ifa->addr->ip);
/* Now we should send a hello packet */
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->addr->pxlen);
ipa_hton(pkt->netmask);
if ((ifa->type == OSPF_IT_VLINK) ||
((ifa->type == OSPF_IT_PTP) && !ifa->ptp_netmask))
pkt->netmask = IPA_NONE;
#endif
pkt->helloint = ntohs(ifa->helloint);
pkt->priority = ifa->priority;
#ifdef OSPFv3
pkt->iface_id = htonl(ifa->iface_id);
pkt->options3 = ifa->oa->options >> 16;
pkt->options2 = ifa->oa->options >> 8;
#endif
pkt->options = ifa->oa->options;
#ifdef OSPFv2
pkt->deadint = htonl(ifa->deadint);
pkt->dr = htonl(ipa_to_u32(ifa->drip));
pkt->bdr = htonl(ipa_to_u32(ifa->bdrip));
#else /* OSPFv3 */
pkt->deadint = htons(ifa->deadint);
pkt->dr = htonl(ifa->drid);
pkt->bdr = htonl(ifa->bdrid);
#endif
if (ospf_is_v2(p))
{
struct ospf_hello2_packet *ps = (void *) pkt;
if ((ifa->type == OSPF_IT_VLINK) ||
((ifa->type == OSPF_IT_PTP) && !ifa->ptp_netmask))
ps->netmask = 0;
else
ps->netmask = htonl(u32_mkmask(ifa->addr->pxlen));
ps->helloint = ntohs(ifa->helloint);
ps->options = ifa->oa->options;
ps->priority = ifa->priority;
ps->deadint = htonl(ifa->deadint);
ps->dr = htonl(ipa_to_u32(ifa->drip));
ps->bdr = htonl(ipa_to_u32(ifa->bdrip));