]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/hello.c
70fb6548ee57063bcf365c4cca4c228c4c85e420
4 * (c) 1999--2004 Ondrej Filip <feela@network.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
13 struct ospf_hello_packet
15 struct ospf_packet ospf_packet
;
28 struct ospf_hello_packet
30 struct ospf_packet ospf_packet
;
45 ospf_hello_receive(struct ospf_packet
*ps_i
, struct ospf_iface
*ifa
,
46 struct ospf_neighbor
*n
, ip_addr faddr
)
48 struct proto_ospf
*po
= ifa
->oa
->po
;
49 struct proto
*p
= &po
->proto
;
50 char *beg
= "OSPF: Bad HELLO packet from ";
51 unsigned int size
, i
, twoway
, eligible
, peers
;
55 size
= ntohs(ps_i
->length
);
56 if (size
< sizeof(struct ospf_hello_packet
))
58 log(L_ERR
"%s%I - too short (%u B)", beg
, faddr
, size
);
62 struct ospf_hello_packet
*ps
= (void *) ps_i
;
64 OSPF_TRACE(D_PACKETS
, "HELLO packet received from %I via %s%s", faddr
,
65 (ifa
->type
== OSPF_IT_VLINK
? "vlink-" : ""), ifa
->iface
->name
);
68 ip_addr mask
= ps
->netmask
;
70 if ((ifa
->type
!= OSPF_IT_VLINK
) &&
71 (ifa
->type
!= OSPF_IT_PTP
) &&
72 !ipa_equal(mask
, ipa_mkmask(ifa
->addr
->pxlen
)))
74 log(L_ERR
"%s%I - netmask mismatch (%I)", beg
, faddr
, mask
);
79 tmp
= ntohs(ps
->helloint
);
80 if (tmp
!= ifa
->helloint
)
82 log(L_ERR
"%s%I - hello interval mismatch (%d)", beg
, faddr
, tmp
);
87 tmp
= ntohl(ps
->deadint
);
89 tmp
= ntohs(ps
->deadint
);
93 log(L_ERR
"%s%I - dead interval mismatch (%d)", beg
, faddr
, tmp
);
97 tmp
= !(ps
->options
& OPT_E
);
98 if (tmp
!= !!ifa
->oa
->stub
)
100 log(L_ERR
"%s%I - stub area flag mismatch (%d)", beg
, faddr
, tmp
);
106 if ((ifa
->type
== OSPF_IT_NBMA
))
108 struct nbma_node
*nn
;
111 WALK_LIST(nn
, ifa
->nbma_list
)
113 if (ipa_equal(faddr
, nn
->ip
))
119 if ((found
== 0) && (ifa
->strictnbma
))
121 log(L_WARN
"Ignoring new neighbor: %I on %s", faddr
,
127 eligible
= nn
->eligible
;
128 if (((ps
->priority
== 0) && eligible
)
129 || ((ps
->priority
> 0) && (eligible
== 0)))
131 log(L_ERR
"Eligibility mismatch for neighbor: %I on %s",
132 faddr
, ifa
->iface
->name
);
137 OSPF_TRACE(D_EVENTS
, "New neighbor found: %I on %s", faddr
,
140 n
= ospf_neighbor_new(ifa
);
142 n
->rid
= ntohl(((struct ospf_packet
*) ps
)->routerid
);
144 n
->dr
= ntohl(ps
->dr
);
145 n
->bdr
= ntohl(ps
->bdr
);
146 n
->priority
= ps
->priority
;
148 n
->iface_id
= ntohl(ps
->iface_id
);
151 ospf_neigh_sm(n
, INM_HELLOREC
);
153 pnrid
= (u32
*) ((struct ospf_hello_packet
*) (ps
+ 1));
155 peers
= (size
- sizeof(struct ospf_hello_packet
))/ sizeof(u32
);
158 for (i
= 0; i
< peers
; i
++)
160 if (ntohl(pnrid
[i
]) == po
->router_id
)
162 DBG("%s: Twoway received from %I\n", p
->name
, faddr
);
163 ospf_neigh_sm(n
, INM_2WAYREC
);
170 ospf_neigh_sm(n
, INM_1WAYREC
);
174 u32 oldpriority
= n
->priority
;
176 u32 oldiface_id
= n
->iface_id
;
179 n
->dr
= ntohl(ps
->dr
);
180 n
->bdr
= ntohl(ps
->bdr
);
181 n
->priority
= ps
->priority
;
183 n
->iface_id
= ntohl(ps
->iface_id
);
187 /* Check priority change */
188 if (n
->state
>= NEIGHBOR_2WAY
)
191 u32 neigh
= ipa_to_u32(n
->ip
);
196 if (n
->priority
!= oldpriority
)
197 ospf_iface_sm(ifa
, ISM_NEICH
);
200 if (n
->iface_id
!= oldiface_id
)
201 ospf_iface_sm(ifa
, ISM_NEICH
);
204 /* Neighbor is declaring itself ad DR and there is no BDR */
205 if ((n
->dr
== neigh
) && (n
->bdr
== 0)
206 && (n
->state
!= NEIGHBOR_FULL
))
207 ospf_iface_sm(ifa
, ISM_BACKS
);
209 /* Neighbor is declaring itself as BDR */
210 if ((n
->bdr
== neigh
) && (n
->state
!= NEIGHBOR_FULL
))
211 ospf_iface_sm(ifa
, ISM_BACKS
);
213 /* Neighbor is newly declaring itself as DR or BDR */
214 if (((n
->dr
== neigh
) && (n
->dr
!= olddr
))
215 || ((n
->bdr
== neigh
) && (n
->bdr
!= oldbdr
)))
216 ospf_iface_sm(ifa
, ISM_NEICH
);
218 /* Neighbor is no more declaring itself as DR or BDR */
219 if (((olddr
== neigh
) && (n
->dr
!= olddr
))
220 || ((oldbdr
== neigh
) && (n
->bdr
!= oldbdr
)))
221 ospf_iface_sm(ifa
, ISM_NEICH
);
224 if (ifa
->type
== OSPF_IT_NBMA
)
226 if ((ifa
->priority
== 0) && (n
->priority
> 0))
227 ospf_hello_send(NULL
, 0, n
);
229 ospf_neigh_sm(n
, INM_HELLOREC
);
233 ospf_hello_send(timer
*timer
, int poll
, struct ospf_neighbor
*dirn
)
235 struct ospf_iface
*ifa
;
236 struct ospf_hello_packet
*pkt
;
237 struct ospf_packet
*op
;
239 struct ospf_neighbor
*neigh
, *n1
;
243 struct nbma_node
*nb
;
248 ifa
= (struct ospf_iface
*) timer
->data
;
250 if (ifa
->state
== OSPF_IS_DOWN
)
254 return; /* Don't send any packet on stub iface */
256 p
= (struct proto
*) (ifa
->oa
->po
);
257 DBG("%s: Hello/Poll timer fired on interface %s with IP %I\n",
258 p
->name
, ifa
->iface
->name
, ifa
->addr
->ip
);
260 /* Now we should send a hello packet */
261 pkt
= ospf_tx_buffer(ifa
);
262 op
= &pkt
->ospf_packet
;
264 /* Now fill ospf_hello header */
265 ospf_pkt_fill_hdr(ifa
, pkt
, HELLO_P
);
268 pkt
->netmask
= ipa_mkmask(ifa
->addr
->pxlen
);
269 ipa_hton(pkt
->netmask
);
270 if ((ifa
->type
== OSPF_IT_VLINK
) || (ifa
->type
== OSPF_IT_PTP
))
271 pkt
->netmask
= IPA_NONE
;
274 pkt
->helloint
= ntohs(ifa
->helloint
);
275 pkt
->priority
= ifa
->priority
;
278 pkt
->iface_id
= htonl(ifa
->iface
->index
);
280 pkt
->options3
= ifa
->oa
->options
>> 16;
281 pkt
->options2
= ifa
->oa
->options
>> 8;
283 pkt
->options
= ifa
->oa
->options
;
286 pkt
->deadint
= htonl(ifa
->dead
);
287 pkt
->dr
= htonl(ipa_to_u32(ifa
->drip
));
288 pkt
->bdr
= htonl(ipa_to_u32(ifa
->bdrip
));
290 pkt
->deadint
= htons(ifa
->dead
);
291 pkt
->dr
= htonl(ifa
->drid
);
292 pkt
->bdr
= htonl(ifa
->bdrid
);
295 /* Fill all neighbors */
297 pp
= (u32
*) (((u8
*) pkt
) + sizeof(struct ospf_hello_packet
));
298 WALK_LIST(neigh
, ifa
->neigh_list
)
300 if ((i
+1) * sizeof(u32
) + sizeof(struct ospf_hello_packet
) > ospf_pkt_maxsize(ifa
))
302 OSPF_TRACE(D_PACKETS
, "Too many neighbors on the interface!");
305 *(pp
+ i
) = htonl(neigh
->rid
);
309 length
= sizeof(struct ospf_hello_packet
) + i
* sizeof(u32
);
310 op
->length
= htons(length
);
315 if (timer
== NULL
) /* Response to received hello */
317 ospf_send_to(ifa
, dirn
->ip
);
323 if (ifa
->state
> OSPF_IS_DROTHER
)
325 if (ifa
->priority
> 0)
328 WALK_LIST(nb
, ifa
->nbma_list
)
331 WALK_LIST(n1
, ifa
->neigh_list
)
333 if (ipa_equal(nb
->ip
, n1
->ip
))
339 if ((poll
== 1) && (send
))
341 if (toall
|| (meeli
&& nb
->eligible
))
342 ospf_send_to(ifa
, nb
->ip
);
347 WALK_LIST(n1
, ifa
->neigh_list
)
349 if (toall
|| (n1
->rid
== ifa
->drid
) || (n1
->rid
== ifa
->bdrid
) ||
350 (meeli
&& (n1
->priority
> 0)))
351 ospf_send_to(ifa
, n1
->ip
);
357 ospf_send_to(ifa
, ifa
->vip
);
360 ospf_send_to(ifa
, AllSPFRouters
);
363 OSPF_TRACE(D_PACKETS
, "HELLO packet sent via %s%s",
364 (ifa
->type
== OSPF_IT_VLINK
? "vlink-" : ""), ifa
->iface
->name
);