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