"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /* $OpenBSD: lsreq.c,v 1.18 2009/06/06 07:31:26 eric Exp $ */
2
3 /*
4 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
23 #include <stdlib.h>
24
25 #include "ospfd.h"
26 #include "ospf.h"
27 #include "log.h"
28 #include "ospfe.h"
29
30 extern struct imsgev *iev_rde;
31
32 /* link state request packet handling */
33 int
34 send_ls_req(struct nbr *nbr)
35 {
36 struct sockaddr_in dst;
37 struct ls_req_hdr ls_req_hdr;
38 struct lsa_entry *le, *nle;
39 struct buf *buf;
40 int ret;
41
42 if ((buf = buf_open(nbr->iface->mtu - sizeof(struct ip))) == NULL)
43 fatal("send_ls_req");
44
45 /* set destination */
46 dst.sin_family = AF_INET;
47 dst.sin_len = sizeof(struct sockaddr_in);
48
49 switch (nbr->iface->type) {
50 case IF_TYPE_POINTOPOINT:
51 inet_aton(AllSPFRouters, &dst.sin_addr);
52 break;
53 case IF_TYPE_BROADCAST:
54 case IF_TYPE_NBMA:
55 case IF_TYPE_POINTOMULTIPOINT:
56 case IF_TYPE_VIRTUALLINK:
57 dst.sin_addr.s_addr = nbr->addr.s_addr;
58 break;
59 default:
60 fatalx("send_ls_req: unknown interface type");
61 }
62
63 /* OSPF header */
64 if (gen_ospf_hdr(buf, nbr->iface, PACKET_TYPE_LS_REQUEST))
65 goto fail;
66
67 /* LSA header(s), keep space for a possible md5 sum */
68 for (le = TAILQ_FIRST(&nbr->ls_req_list); le != NULL &&
69 buf_left(buf) >= sizeof(struct ls_req_hdr) + MD5_DIGEST_LENGTH;
70 le = nle) {
71 nbr->ls_req = nle = TAILQ_NEXT(le, entry);
72 ls_req_hdr.type = htonl(le->le_lsa->type);
73 ls_req_hdr.ls_id = le->le_lsa->ls_id;
74 ls_req_hdr.adv_rtr = le->le_lsa->adv_rtr;
75 if (buf_add(buf, &ls_req_hdr, sizeof(ls_req_hdr)))
76 goto fail;
77 }
78
79 /* update authentication and calculate checksum */
80 if (auth_gen(buf, nbr->iface))
81 goto fail;
82
83 ret = send_packet(nbr->iface, buf, &dst);
84
85 buf_free(buf);
86 return (ret);
87 fail:
88 log_warn("send_ls_req");
89 buf_free(buf);
90 return (-1);
91 }
92
93 void
94 recv_ls_req(struct nbr *nbr, char *buf, u_int16_t len)
95 {
96 switch (nbr->state) {
97 case NBR_STA_DOWN:
98 case NBR_STA_ATTEMPT:
99 case NBR_STA_INIT:
100 case NBR_STA_2_WAY:
101 case NBR_STA_XSTRT:
102 case NBR_STA_SNAP:
103 log_debug("recv_ls_req: packet ignored in state %s, "
104 "neighbor ID %s", nbr_state_name(nbr->state),
105 inet_ntoa(nbr->id));
106 break;
107 case NBR_STA_XCHNG:
108 case NBR_STA_LOAD:
109 case NBR_STA_FULL:
110 imsg_compose_event(iev_rde, IMSG_LS_REQ, nbr->peerid,
111 0, -1, buf, len);
112 break;
113 default:
114 fatalx("recv_ls_req: unknown neighbor state");
115 }
116 }
117
118 /* link state request list */
119 void
120 ls_req_list_add(struct nbr *nbr, struct lsa_hdr *lsa)
121 {
122 struct lsa_entry *le;
123
124 if (lsa == NULL)
125 fatalx("ls_req_list_add: no LSA header");
126
127 if ((le = calloc(1, sizeof(*le))) == NULL)
128 fatal("ls_req_list_add");
129
130 TAILQ_INSERT_TAIL(&nbr->ls_req_list, le, entry);
131 le->le_lsa = lsa;
132 nbr->ls_req_cnt++;
133 }
134
135 struct lsa_entry *
136 ls_req_list_get(struct nbr *nbr, struct lsa_hdr *lsa_hdr)
137 {
138 struct lsa_entry *le;
139
140 TAILQ_FOREACH(le, &nbr->ls_req_list, entry) {
141 if ((lsa_hdr->type == le->le_lsa->type) &&
142 (lsa_hdr->ls_id == le->le_lsa->ls_id) &&
143 (lsa_hdr->adv_rtr == le->le_lsa->adv_rtr))
144 return (le);
145 }
146 return (NULL);
147 }
148
149 void
150 ls_req_list_free(struct nbr *nbr, struct lsa_entry *le)
151 {
152 if (nbr->ls_req == le) {
153 nbr->ls_req = TAILQ_NEXT(le, entry);
154 }
155
156 TAILQ_REMOVE(&nbr->ls_req_list, le, entry);
157 free(le->le_lsa);
158 free(le);
159 nbr->ls_req_cnt--;
160
161 /* received all requested LSA(s), send a new LS req */
162 if (nbr->ls_req != NULL &&
163 nbr->ls_req == TAILQ_FIRST(&nbr->ls_req_list)) {
164 start_ls_req_tx_timer(nbr);
165 }
166
167 if (ls_req_list_empty(nbr) && nbr->dd_pending == 0)
168 nbr_fsm(nbr, NBR_EVT_LOAD_DONE);
169 }
170
171 void
172 ls_req_list_clr(struct nbr *nbr)
173 {
174 struct lsa_entry *le;
175
176 while ((le = TAILQ_FIRST(&nbr->ls_req_list)) != NULL) {
177 TAILQ_REMOVE(&nbr->ls_req_list, le, entry);
178 free(le->le_lsa);
179 free(le);
180 }
181
182 nbr->ls_req_cnt = 0;
183 nbr->ls_req = NULL;
184 }
185
186 int
187 ls_req_list_empty(struct nbr *nbr)
188 {
189 return (TAILQ_EMPTY(&nbr->ls_req_list));
190 }
191
192 /* timers */
193 /* ARGSUSED */
194 void
195 ls_req_tx_timer(int fd, short event, void *arg)
196 {
197 struct nbr *nbr = arg;
198 struct timeval tv;
199
200 switch (nbr->state) {
201 case NBR_STA_DOWN:
202 case NBR_STA_ATTEMPT:
203 case NBR_STA_INIT:
204 case NBR_STA_2_WAY:
205 case NBR_STA_SNAP:
206 case NBR_STA_XSTRT:
207 case NBR_STA_XCHNG:
208 return;
209 case NBR_STA_LOAD:
210 send_ls_req(nbr);
211 break;
212 case NBR_STA_FULL:
213 return;
214 default:
215 log_debug("ls_req_tx_timer: unknown neighbor state, "
216 "neighbor ID %s", inet_ntoa(nbr->id));
217 break;
218 }
219
220 /* reschedule lsreq_tx_timer */
221 if (nbr->state == NBR_STA_LOAD) {
222 timerclear(&tv);
223 tv.tv_sec = nbr->iface->rxmt_interval;
224 if (evtimer_add(&nbr->lsreq_tx_timer, &tv) == -1)
225 fatal("ls_req_tx_timer");
226 }
227 }
228
229 void
230 start_ls_req_tx_timer(struct nbr *nbr)
231 {
232 struct timeval tv;
233
234 if (nbr == nbr->iface->self)
235 return;
236
237 timerclear(&tv);
238 if (evtimer_add(&nbr->lsreq_tx_timer, &tv) == -1)
239 fatal("start_ls_req_tx_timer");
240 }
241
242 void
243 stop_ls_req_tx_timer(struct nbr *nbr)
244 {
245 if (nbr == nbr->iface->self)
246 return;
247
248 if (evtimer_del(&nbr->lsreq_tx_timer) == -1)
249 fatal("stop_ls_req_tx_timer");
250 }