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