plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

ospf.c (7359B)


      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 };