]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ip/snoopy/ospf.c
snoopy(8): avoid extra spaces in dhcp filter output
[plan9front.git] / sys / src / cmd / ip / snoopy / ospf.c
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*
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*
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*
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*
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*
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*
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*
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*
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
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 };