1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include <libsec.h>
5 #include "dat.h"
6 #include "protos.h"
7
8
9 /*
10 * OSPF packets
11 */
12 typedef struct Ospfpkt Ospfpkt;
13 struct Ospfpkt
14 {
15 uchar version;
16 uchar type;
17 uchar length[2];
18 uchar router[4];
19 uchar area[4];
20 uchar sum[2];
21 uchar autype[2];
22 uchar auth[8];
23 uchar data[1];
24 };
25 #define OSPF_HDRSIZE 24
26
27 enum
28 {
29 OSPFhello= 1,
30 OSPFdd= 2,
31 OSPFlsrequest= 3,
32 OSPFlsupdate= 4,
33 OSPFlsack= 5
34 };
35
36
37 char *ospftype[] = {
38 [OSPFhello] "hello",
39 [OSPFdd] "data definition",
40 [OSPFlsrequest] "link state request",
41 [OSPFlsupdate] "link state update",
42 [OSPFlsack] "link state ack"
43 };
44
45 char*
ospfpkttype(int x)46 ospfpkttype(int x)
47 {
48 static char type[16];
49
50 if(x > 0 && x <= OSPFlsack)
51 return ospftype[x];
52 sprint(type, "type %d", x);
53 return type;
54 }
55
56 char*
ospfauth(Ospfpkt * ospf)57 ospfauth(Ospfpkt *ospf)
58 {
59 static char auth[100];
60
61 switch(ospf->type){
62 case 0:
63 return "no authentication";
64 case 1:
65 sprint(auth, "password(%8.8ux %8.8ux)", NetL(ospf->auth),
66 NetL(ospf->auth+4));
67 break;
68 case 2:
69 sprint(auth, "crypto(plen %d id %d dlen %d)", NetS(ospf->auth),
70 ospf->auth[2], ospf->auth[3]);
71 break;
72 default:
73 sprint(auth, "auth%d(%8.8ux %8.8ux)", NetS(ospf->autype), NetL(ospf->auth),
74 NetL(ospf->auth+4));
75 }
76 return auth;
77 }
78
79 typedef struct Ospfhello Ospfhello;
80 struct Ospfhello
81 {
82 uchar mask[4];
83 uchar interval[2];
84 uchar options;
85 uchar pri;
86 uchar deadint[4];
87 uchar designated[4];
88 uchar bdesignated[4];
89 uchar neighbor[1];
90 };
91
92 char*
seprintospfhello(char * p,char * e,void * a)93 seprintospfhello(char *p, char *e, void *a)
94 {
95 Ospfhello *h = a;
96
97 return seprint(p, e, "%s(mask %V interval %d opt %ux pri %ux deadt %d designated %V bdesignated %V)",
98 ospftype[OSPFhello],
99 h->mask, NetS(h->interval), h->options, h->pri,
100 NetL(h->deadint), h->designated, h->bdesignated);
101 }
102
103 enum
104 {
105 LSARouter= 1,
106 LSANetwork= 2,
107 LSASummN= 3,
108 LSASummR= 4,
109 LSAASext= 5
110 };
111
112
113 char *lsatype[] = {
114 [LSARouter] "Router LSA",
115 [LSANetwork] "Network LSA",
116 [LSASummN] "Summary LSA (Network)",
117 [LSASummR] "Summary LSA (Router)",
118 [LSAASext] "LSA AS external"
119 };
120
121 char*
lsapkttype(int x)122 lsapkttype(int x)
123 {
124 static char type[16];
125
126 if(x > 0 && x <= LSAASext)
127 return lsatype[x];
128 sprint(type, "type %d", x);
129 return type;
130 }
131
132 /* OSPF Link State Advertisement Header */
133 /* rfc2178 section 12.1 */
134 /* data of Ospfpkt point to a 4-uchar value that is the # of LSAs */
135 struct OspfLSAhdr {
136 uchar lsage[2];
137 uchar options; /* 0x2=stub area, 0x1=TOS routing capable */
138
139 uchar lstype; /* 1=Router-LSAs
140 * 2=Network-LSAs
141 * 3=Summary-LSAs (to network)
142 * 4=Summary-LSAs (to AS boundary routers)
143 * 5=AS-External-LSAs
144 */
145 uchar lsid[4];
146 uchar advtrt[4];
147
148 uchar lsseqno[4];
149 uchar lscksum[2];
150 uchar lsalen[2]; /* includes the 20 byte lsa header */
151 };
152
153 struct Ospfrt {
154 uchar linkid[4];
155 uchar linkdata[4];
156 uchar typ;
157 uchar numtos;
158 uchar metric[2];
159
160 };
161
162 struct OspfrtLSA {
163 struct OspfLSAhdr hdr;
164 uchar netmask[4];
165 };
166
167 struct OspfntLSA {
168 struct OspfLSAhdr hdr;
169 uchar netmask[4];
170 uchar attrt[4];
171 };
172
173 /* Summary Link State Advertisement info */
174 struct Ospfsumm {
175 uchar flag; /* always zero */
176 uchar metric[3];
177 };
178
179 struct OspfsummLSA {
180 struct OspfLSAhdr hdr;
181 uchar netmask[4];
182 struct Ospfsumm lsa;
183 };
184
185 /* AS external Link State Advertisement info */
186 struct OspfASext {
187 uchar flag; /* external */
188 uchar metric[3];
189 uchar fwdaddr[4];
190 uchar exrttag[4];
191 };
192
193 struct OspfASextLSA {
194 struct OspfLSAhdr hdr;
195 uchar netmask[4];
196 struct OspfASext lsa;
197 };
198
199 /* OSPF Link State Update Packet */
200 struct OspfLSupdpkt {
201 uchar lsacnt[4];
202 union {
203 uchar hdr[1];
204 struct OspfrtLSA rt[1];
205 struct OspfntLSA nt[1];
206 struct OspfsummLSA sum[1];
207 struct OspfASextLSA as[1];
208 };
209 };
210
211 char*
seprintospflsaheader(char * p,char * e,struct OspfLSAhdr * h)212 seprintospflsaheader(char *p, char *e, struct OspfLSAhdr *h)
213 {
214 return seprint(p, e, "age %d opt %ux type %ux lsid %V adv_rt %V seqno %ux c %4.4ux l %d",
215 NetS(h->lsage), h->options&0xff, h->lstype,
216 h->lsid, h->advtrt, NetL(h->lsseqno), NetS(h->lscksum),
217 NetS(h->lsalen));
218 }
219
220 /* OSPF Database Description Packet */
221 struct OspfDDpkt {
222 uchar intMTU[2];
223 uchar options;
224 uchar bits;
225 uchar DDseqno[4];
226 struct OspfLSAhdr hdr[1]; /* LSA headers... */
227 };
228
229 char*
seprintospfdatadesc(char * p,char * e,void * a,int len)230 seprintospfdatadesc(char *p, char *e, void *a, int len)
231 {
232 int nlsa, i;
233 struct OspfDDpkt *g;
234
235 g = (struct OspfDDpkt *)a;
236 nlsa = len/sizeof(struct OspfLSAhdr);
237 for (i=0; i<nlsa; i++) {
238 p = seprint(p, e, "lsa%d(", i);
239 p = seprintospflsaheader(p, e, &(g->hdr[i]));
240 p = seprint(p, e, ")");
241 }
242 return seprint(p, e, ")");
243 }
244
245 char*
seprintospflsupdate(char * p,char * e,void * a,int len)246 seprintospflsupdate(char *p, char *e, void *a, int len)
247 {
248 int nlsa, i;
249 struct OspfLSupdpkt *g;
250 struct OspfLSAhdr *h;
251
252 g = (struct OspfLSupdpkt *)a;
253 nlsa = NetL(g->lsacnt);
254 h = (struct OspfLSAhdr *)(g->hdr);
255 p = seprint(p, e, "%d-%s(", nlsa, ospfpkttype(OSPFlsupdate));
256
257 switch(h->lstype) {
258 case LSARouter:
259 {
260 /* struct OspfrtLSA *h;
261 */
262 }
263 break;
264 case LSANetwork:
265 {
266 struct OspfntLSA *h;
267
268 for (i=0; i<nlsa; i++) {
269 h = &(g->nt[i]);
270 p = seprint(p, e, "lsa%d(", i);
271 p = seprintospflsaheader(p, e, &(h->hdr));
272 p = seprint(p, e, " mask %V attrt %V)",
273 h->netmask, h->attrt);
274 }
275 }
276 break;
277 case LSASummN:
278 case LSASummR:
279 {
280 struct OspfsummLSA *h;
281
282 for (i=0; i<nlsa; i++) {
283 h = &(g->sum[i]);
284 p = seprint(p, e, "lsa%d(", i);
285 p = seprintospflsaheader(p, e, &(h->hdr));
286 p = seprint(p, e, " mask %V met %d)",
287 h->netmask, Net3(h->lsa.metric));
288 }
289 }
290 break;
291 case LSAASext:
292 {
293 struct OspfASextLSA *h;
294
295 for (i=0; i<nlsa; i++) {
296 h = &(g->as[i]);
297 p = seprint(p, e, " lsa%d(", i);
298 p = seprintospflsaheader(p, e, &(h->hdr));
299 p = seprint(p, e, " mask %V extflg %1.1ux met %d fwdaddr %V extrtflg %ux)",
300 h->netmask, h->lsa.flag, Net3(h->lsa.metric),
301 h->lsa.fwdaddr, NetL(h->lsa.exrttag));
302 }
303 }
304 break;
305 default:
306 p = seprint(p, e, "Not an LS update, lstype %d ", h->lstype);
307 p = seprint(p, e, " %.*H", len>64?64:len, a);
308 break;
309 }
310 return seprint(p, e, ")");
311 }
312
313 char*
seprintospflsack(char * p,char * e,void * a,int len)314 seprintospflsack(char *p, char *e, void *a, int len)
315 {
316 int nlsa, i;
317 struct OspfLSAhdr *h;
318
319 h = (struct OspfLSAhdr *)a;
320 nlsa = len/sizeof(struct OspfLSAhdr);
321 p = seprint(p, e, "%d-%s(", nlsa, ospfpkttype(OSPFlsack));
322 for (i=0; i<nlsa; i++) {
323 p = seprint(p, e, " lsa%d(", i);
324 p = seprintospflsaheader(p, e, &(h[i]));
325 p = seprint(p, e, ")");
326 }
327 return seprint(p, e, ")");
328 }
329
330 int
p_seprint(Msg * m)331 p_seprint(Msg *m)
332 {
333 Ospfpkt *ospf;
334 int len, x;
335 char *p, *e;
336
337 len = m->pe - m->ps;
338 if(len < OSPF_HDRSIZE)
339 return -1;
340 p = m->p;
341 e = m->e;
342
343 /* adjust packet size */
344 ospf = (Ospfpkt*)m->ps;
345 x = NetS(ospf->length);
346 if(x < len)
347 return -1;
348 x -= OSPF_HDRSIZE;
349
350 p = seprint(p, e, "ver=%d type=%d len=%d r=%V a=%V c=%4.4ux %s ",
351 ospf->version, ospf->type, x,
352 ospf->router, ospf->area, NetS(ospf->sum),
353 ospfauth(ospf));
354
355 switch (ospf->type) {
356 case OSPFhello:
357 p = seprintospfhello(p, e, ospf->data);
358 break;
359 case OSPFdd:
360 p = seprintospfdatadesc(p, e, ospf->data, x);
361 break;
362 case OSPFlsrequest:
363 p = seprint(p, e, " %s->", ospfpkttype(ospf->type));
364 goto Default;
365 case OSPFlsupdate:
366 p = seprintospflsupdate(p, e, ospf->data, x);
367 break;
368 case OSPFlsack:
369 p = seprintospflsack(p, e, ospf->data, x);
370 break;
371 default:
372 Default:
373 p = seprint(p, e, " data=%.*H", x>64?64:x, ospf->data);
374 }
375 m->p = p;
376 m->pr = nil;
377 return 0;
378 }
379
380 Proto ospf =
381 {
382 "ospf",
383 nil,
384 nil,
385 p_seprint,
386 nil,
387 nil,
388 nil,
389 defaultframer
390 };
391