19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <ip.h>
49a747e4fSDavid du Colombier #include <libsec.h>
59a747e4fSDavid du Colombier #include "dat.h"
69a747e4fSDavid du Colombier #include "protos.h"
79a747e4fSDavid du Colombier
89a747e4fSDavid du Colombier
99a747e4fSDavid du Colombier /*
109a747e4fSDavid du Colombier * OSPF packets
119a747e4fSDavid du Colombier */
129a747e4fSDavid du Colombier typedef struct Ospfpkt Ospfpkt;
139a747e4fSDavid du Colombier struct Ospfpkt
149a747e4fSDavid du Colombier {
159a747e4fSDavid du Colombier uchar version;
169a747e4fSDavid du Colombier uchar type;
179a747e4fSDavid du Colombier uchar length[2];
189a747e4fSDavid du Colombier uchar router[4];
199a747e4fSDavid du Colombier uchar area[4];
209a747e4fSDavid du Colombier uchar sum[2];
219a747e4fSDavid du Colombier uchar autype[2];
229a747e4fSDavid du Colombier uchar auth[8];
239a747e4fSDavid du Colombier uchar data[1];
249a747e4fSDavid du Colombier };
259a747e4fSDavid du Colombier #define OSPF_HDRSIZE 24
269a747e4fSDavid du Colombier
279a747e4fSDavid du Colombier enum
289a747e4fSDavid du Colombier {
299a747e4fSDavid du Colombier OSPFhello= 1,
309a747e4fSDavid du Colombier OSPFdd= 2,
319a747e4fSDavid du Colombier OSPFlsrequest= 3,
329a747e4fSDavid du Colombier OSPFlsupdate= 4,
339a747e4fSDavid du Colombier OSPFlsack= 5,
349a747e4fSDavid du Colombier };
359a747e4fSDavid du Colombier
369a747e4fSDavid du Colombier
379a747e4fSDavid du Colombier char *ospftype[] = {
389a747e4fSDavid du Colombier [OSPFhello] "hello",
399a747e4fSDavid du Colombier [OSPFdd] "data definition",
409a747e4fSDavid du Colombier [OSPFlsrequest] "link state request",
419a747e4fSDavid du Colombier [OSPFlsupdate] "link state update",
429a747e4fSDavid du Colombier [OSPFlsack] "link state ack",
439a747e4fSDavid du Colombier };
449a747e4fSDavid du Colombier
459a747e4fSDavid du Colombier char*
ospfpkttype(int x)469a747e4fSDavid du Colombier ospfpkttype(int x)
479a747e4fSDavid du Colombier {
489a747e4fSDavid du Colombier static char type[16];
499a747e4fSDavid du Colombier
509a747e4fSDavid du Colombier if(x > 0 && x <= OSPFlsack)
519a747e4fSDavid du Colombier return ospftype[x];
529a747e4fSDavid du Colombier sprint(type, "type %d", x);
539a747e4fSDavid du Colombier return type;
549a747e4fSDavid du Colombier }
559a747e4fSDavid du Colombier
569a747e4fSDavid du Colombier char*
ospfauth(Ospfpkt * ospf)579a747e4fSDavid du Colombier ospfauth(Ospfpkt *ospf)
589a747e4fSDavid du Colombier {
599a747e4fSDavid du Colombier static char auth[100];
609a747e4fSDavid du Colombier
619a747e4fSDavid du Colombier switch(ospf->type){
629a747e4fSDavid du Colombier case 0:
639a747e4fSDavid du Colombier return "no authentication";
649a747e4fSDavid du Colombier case 1:
659a747e4fSDavid du Colombier sprint(auth, "password(%8.8ux %8.8ux)", NetL(ospf->auth),
669a747e4fSDavid du Colombier NetL(ospf->auth+4));
679a747e4fSDavid du Colombier break;
689a747e4fSDavid du Colombier case 2:
699a747e4fSDavid du Colombier sprint(auth, "crypto(plen %d id %d dlen %d)", NetS(ospf->auth),
709a747e4fSDavid du Colombier ospf->auth[2], ospf->auth[3]);
719a747e4fSDavid du Colombier break;
729a747e4fSDavid du Colombier default:
739a747e4fSDavid du Colombier sprint(auth, "auth%d(%8.8ux %8.8ux)", NetS(ospf->autype), NetL(ospf->auth),
749a747e4fSDavid du Colombier NetL(ospf->auth+4));
759a747e4fSDavid du Colombier }
769a747e4fSDavid du Colombier return auth;
779a747e4fSDavid du Colombier }
789a747e4fSDavid du Colombier
799a747e4fSDavid du Colombier typedef struct Ospfhello Ospfhello;
809a747e4fSDavid du Colombier struct Ospfhello
819a747e4fSDavid du Colombier {
829a747e4fSDavid du Colombier uchar mask[4];
839a747e4fSDavid du Colombier uchar interval[2];
849a747e4fSDavid du Colombier uchar options;
859a747e4fSDavid du Colombier uchar pri;
869a747e4fSDavid du Colombier uchar deadint[4];
879a747e4fSDavid du Colombier uchar designated[4];
889a747e4fSDavid du Colombier uchar bdesignated[4];
899a747e4fSDavid du Colombier uchar neighbor[1];
909a747e4fSDavid du Colombier };
919a747e4fSDavid du Colombier
929a747e4fSDavid du Colombier char*
seprintospfhello(char * p,char * e,void * a)93*2cca75a1SDavid du Colombier seprintospfhello(char *p, char *e, void *a)
949a747e4fSDavid du Colombier {
959a747e4fSDavid du Colombier Ospfhello *h = a;
969a747e4fSDavid du Colombier
979a747e4fSDavid du Colombier return seprint(p, e, "%s(mask %V interval %d opt %ux pri %ux deadt %d designated %V bdesignated %V)",
989a747e4fSDavid du Colombier ospftype[OSPFhello],
999a747e4fSDavid du Colombier h->mask, NetS(h->interval), h->options, h->pri,
1009a747e4fSDavid du Colombier NetL(h->deadint), h->designated, h->bdesignated);
1019a747e4fSDavid du Colombier }
1029a747e4fSDavid du Colombier
1039a747e4fSDavid du Colombier enum
1049a747e4fSDavid du Colombier {
1059a747e4fSDavid du Colombier LSARouter= 1,
1069a747e4fSDavid du Colombier LSANetwork= 2,
1079a747e4fSDavid du Colombier LSASummN= 3,
1089a747e4fSDavid du Colombier LSASummR= 4,
1099a747e4fSDavid du Colombier LSAASext= 5
1109a747e4fSDavid du Colombier };
1119a747e4fSDavid du Colombier
1129a747e4fSDavid du Colombier
1139a747e4fSDavid du Colombier char *lsatype[] = {
1149a747e4fSDavid du Colombier [LSARouter] "Router LSA",
1159a747e4fSDavid du Colombier [LSANetwork] "Network LSA",
1169a747e4fSDavid du Colombier [LSASummN] "Summary LSA (Network)",
1179a747e4fSDavid du Colombier [LSASummR] "Summary LSA (Router)",
1189a747e4fSDavid du Colombier [LSAASext] "LSA AS external",
1199a747e4fSDavid du Colombier };
1209a747e4fSDavid du Colombier
1219a747e4fSDavid du Colombier char*
lsapkttype(int x)1229a747e4fSDavid du Colombier lsapkttype(int x)
1239a747e4fSDavid du Colombier {
1249a747e4fSDavid du Colombier static char type[16];
1259a747e4fSDavid du Colombier
1269a747e4fSDavid du Colombier if(x > 0 && x <= LSAASext)
1279a747e4fSDavid du Colombier return lsatype[x];
1289a747e4fSDavid du Colombier sprint(type, "type %d", x);
1299a747e4fSDavid du Colombier return type;
1309a747e4fSDavid du Colombier }
1319a747e4fSDavid du Colombier
1329a747e4fSDavid du Colombier /* OSPF Link State Advertisement Header */
1339a747e4fSDavid du Colombier /* rfc2178 section 12.1 */
1349a747e4fSDavid du Colombier /* data of Ospfpkt point to a 4-uchar value that is the # of LSAs */
1359a747e4fSDavid du Colombier struct OspfLSAhdr {
1369a747e4fSDavid du Colombier uchar lsage[2];
1379a747e4fSDavid du Colombier uchar options; /* 0x2=stub area, 0x1=TOS routing capable */
1389a747e4fSDavid du Colombier
1399a747e4fSDavid du Colombier uchar lstype; /* 1=Router-LSAs
1409a747e4fSDavid du Colombier * 2=Network-LSAs
1419a747e4fSDavid du Colombier * 3=Summary-LSAs (to network)
1429a747e4fSDavid du Colombier * 4=Summary-LSAs (to AS boundary routers)
1439a747e4fSDavid du Colombier * 5=AS-External-LSAs
1449a747e4fSDavid du Colombier */
1459a747e4fSDavid du Colombier uchar lsid[4];
1469a747e4fSDavid du Colombier uchar advtrt[4];
1479a747e4fSDavid du Colombier
1489a747e4fSDavid du Colombier uchar lsseqno[4];
1499a747e4fSDavid du Colombier uchar lscksum[2];
1509a747e4fSDavid du Colombier uchar lsalen[2]; /* includes the 20 byte lsa header */
1519a747e4fSDavid du Colombier };
1529a747e4fSDavid du Colombier
1539a747e4fSDavid du Colombier struct Ospfrt {
1549a747e4fSDavid du Colombier uchar linkid[4];
1559a747e4fSDavid du Colombier uchar linkdata[4];
1569a747e4fSDavid du Colombier uchar typ;
1579a747e4fSDavid du Colombier uchar numtos;
1589a747e4fSDavid du Colombier uchar metric[2];
1599a747e4fSDavid du Colombier
1609a747e4fSDavid du Colombier };
1619a747e4fSDavid du Colombier
1629a747e4fSDavid du Colombier struct OspfrtLSA {
1639a747e4fSDavid du Colombier struct OspfLSAhdr hdr;
1649a747e4fSDavid du Colombier uchar netmask[4];
1659a747e4fSDavid du Colombier };
1669a747e4fSDavid du Colombier
1679a747e4fSDavid du Colombier struct OspfntLSA {
1689a747e4fSDavid du Colombier struct OspfLSAhdr hdr;
1699a747e4fSDavid du Colombier uchar netmask[4];
1709a747e4fSDavid du Colombier uchar attrt[4];
1719a747e4fSDavid du Colombier };
1729a747e4fSDavid du Colombier
1739a747e4fSDavid du Colombier /* Summary Link State Advertisement info */
1749a747e4fSDavid du Colombier struct Ospfsumm {
1759a747e4fSDavid du Colombier uchar flag; /* always zero */
1769a747e4fSDavid du Colombier uchar metric[3];
1779a747e4fSDavid du Colombier };
1789a747e4fSDavid du Colombier
1799a747e4fSDavid du Colombier struct OspfsummLSA {
1809a747e4fSDavid du Colombier struct OspfLSAhdr hdr;
1819a747e4fSDavid du Colombier uchar netmask[4];
1829a747e4fSDavid du Colombier struct Ospfsumm lsa;
1839a747e4fSDavid du Colombier };
1849a747e4fSDavid du Colombier
1859a747e4fSDavid du Colombier /* AS external Link State Advertisement info */
1869a747e4fSDavid du Colombier struct OspfASext {
1879a747e4fSDavid du Colombier uchar flag; /* external */
1889a747e4fSDavid du Colombier uchar metric[3];
1899a747e4fSDavid du Colombier uchar fwdaddr[4];
1909a747e4fSDavid du Colombier uchar exrttag[4];
1919a747e4fSDavid du Colombier };
1929a747e4fSDavid du Colombier
1939a747e4fSDavid du Colombier struct OspfASextLSA {
1949a747e4fSDavid du Colombier struct OspfLSAhdr hdr;
1959a747e4fSDavid du Colombier uchar netmask[4];
1969a747e4fSDavid du Colombier struct OspfASext lsa;
1979a747e4fSDavid du Colombier };
1989a747e4fSDavid du Colombier
1999a747e4fSDavid du Colombier /* OSPF Link State Update Packet */
2009a747e4fSDavid du Colombier struct OspfLSupdpkt {
2019a747e4fSDavid du Colombier uchar lsacnt[4];
2029a747e4fSDavid du Colombier union {
2039a747e4fSDavid du Colombier uchar hdr[1];
2049a747e4fSDavid du Colombier struct OspfrtLSA rt[1];
2059a747e4fSDavid du Colombier struct OspfntLSA nt[1];
2069a747e4fSDavid du Colombier struct OspfsummLSA sum[1];
2079a747e4fSDavid du Colombier struct OspfASextLSA as[1];
2089a747e4fSDavid du Colombier };
2099a747e4fSDavid du Colombier };
2109a747e4fSDavid du Colombier
2119a747e4fSDavid du Colombier char*
seprintospflsaheader(char * p,char * e,struct OspfLSAhdr * h)2129a747e4fSDavid du Colombier seprintospflsaheader(char *p, char *e, struct OspfLSAhdr *h)
2139a747e4fSDavid du Colombier {
2149a747e4fSDavid du Colombier return seprint(p, e, "age %d opt %ux type %ux lsid %V adv_rt %V seqno %ux c %4.4ux l %d",
2159a747e4fSDavid du Colombier NetS(h->lsage), h->options&0xff, h->lstype,
2169a747e4fSDavid du Colombier h->lsid, h->advtrt, NetL(h->lsseqno), NetS(h->lscksum),
2179a747e4fSDavid du Colombier NetS(h->lsalen));
2189a747e4fSDavid du Colombier }
2199a747e4fSDavid du Colombier
2209a747e4fSDavid du Colombier /* OSPF Database Description Packet */
2219a747e4fSDavid du Colombier struct OspfDDpkt {
2229a747e4fSDavid du Colombier uchar intMTU[2];
2239a747e4fSDavid du Colombier uchar options;
2249a747e4fSDavid du Colombier uchar bits;
2259a747e4fSDavid du Colombier uchar DDseqno[4];
2269a747e4fSDavid du Colombier struct OspfLSAhdr hdr[1]; /* LSA headers... */
2279a747e4fSDavid du Colombier };
2289a747e4fSDavid du Colombier
2299a747e4fSDavid du Colombier char*
seprintospfdatadesc(char * p,char * e,void * a,int len)2309a747e4fSDavid du Colombier seprintospfdatadesc(char *p, char *e, void *a, int len)
2319a747e4fSDavid du Colombier {
2329a747e4fSDavid du Colombier int nlsa, i;
2339a747e4fSDavid du Colombier struct OspfDDpkt *g;
2349a747e4fSDavid du Colombier
2359a747e4fSDavid du Colombier g = (struct OspfDDpkt *)a;
2369a747e4fSDavid du Colombier nlsa = len/sizeof(struct OspfLSAhdr);
2379a747e4fSDavid du Colombier for (i=0; i<nlsa; i++) {
2389a747e4fSDavid du Colombier p = seprint(p, e, "lsa%d(", i);
2399a747e4fSDavid du Colombier p = seprintospflsaheader(p, e, &(g->hdr[i]));
2409a747e4fSDavid du Colombier p = seprint(p, e, ")");
2419a747e4fSDavid du Colombier }
2429a747e4fSDavid du Colombier return seprint(p, e, ")");
2439a747e4fSDavid du Colombier }
2449a747e4fSDavid du Colombier
2459a747e4fSDavid du Colombier char*
seprintospflsupdate(char * p,char * e,void * a,int len)2469a747e4fSDavid du Colombier seprintospflsupdate(char *p, char *e, void *a, int len)
2479a747e4fSDavid du Colombier {
2489a747e4fSDavid du Colombier int nlsa, i;
2499a747e4fSDavid du Colombier struct OspfLSupdpkt *g;
2509a747e4fSDavid du Colombier struct OspfLSAhdr *h;
2519a747e4fSDavid du Colombier
2529a747e4fSDavid du Colombier g = (struct OspfLSupdpkt *)a;
2539a747e4fSDavid du Colombier nlsa = NetL(g->lsacnt);
2549a747e4fSDavid du Colombier h = (struct OspfLSAhdr *)(g->hdr);
2559a747e4fSDavid du Colombier p = seprint(p, e, "%d-%s(", nlsa, ospfpkttype(OSPFlsupdate));
2569a747e4fSDavid du Colombier
2579a747e4fSDavid du Colombier switch(h->lstype) {
2589a747e4fSDavid du Colombier case LSARouter:
2599a747e4fSDavid du Colombier {
2609a747e4fSDavid du Colombier /* struct OspfrtLSA *h;
2619a747e4fSDavid du Colombier */
2629a747e4fSDavid du Colombier }
2639a747e4fSDavid du Colombier break;
2649a747e4fSDavid du Colombier case LSANetwork:
2659a747e4fSDavid du Colombier {
2669a747e4fSDavid du Colombier struct OspfntLSA *h;
2679a747e4fSDavid du Colombier
2689a747e4fSDavid du Colombier for (i=0; i<nlsa; i++) {
2699a747e4fSDavid du Colombier h = &(g->nt[i]);
2709a747e4fSDavid du Colombier p = seprint(p, e, "lsa%d(", i);
2719a747e4fSDavid du Colombier p = seprintospflsaheader(p, e, &(h->hdr));
2729a747e4fSDavid du Colombier p = seprint(p, e, " mask %V attrt %V)",
2739a747e4fSDavid du Colombier h->netmask, h->attrt);
2749a747e4fSDavid du Colombier }
2759a747e4fSDavid du Colombier }
2769a747e4fSDavid du Colombier break;
2779a747e4fSDavid du Colombier case LSASummN:
2789a747e4fSDavid du Colombier case LSASummR:
2799a747e4fSDavid du Colombier {
2809a747e4fSDavid du Colombier struct OspfsummLSA *h;
2819a747e4fSDavid du Colombier
2829a747e4fSDavid du Colombier for (i=0; i<nlsa; i++) {
2839a747e4fSDavid du Colombier h = &(g->sum[i]);
2849a747e4fSDavid du Colombier p = seprint(p, e, "lsa%d(", i);
2859a747e4fSDavid du Colombier p = seprintospflsaheader(p, e, &(h->hdr));
2869a747e4fSDavid du Colombier p = seprint(p, e, " mask %V met %d)",
2879a747e4fSDavid du Colombier h->netmask, Net3(h->lsa.metric));
2889a747e4fSDavid du Colombier }
2899a747e4fSDavid du Colombier }
2909a747e4fSDavid du Colombier break;
2919a747e4fSDavid du Colombier case LSAASext:
2929a747e4fSDavid du Colombier {
2939a747e4fSDavid du Colombier struct OspfASextLSA *h;
2949a747e4fSDavid du Colombier
2959a747e4fSDavid du Colombier for (i=0; i<nlsa; i++) {
2969a747e4fSDavid du Colombier h = &(g->as[i]);
2979a747e4fSDavid du Colombier p = seprint(p, e, " lsa%d(", i);
2989a747e4fSDavid du Colombier p = seprintospflsaheader(p, e, &(h->hdr));
2999a747e4fSDavid du Colombier p = seprint(p, e, " mask %V extflg %1.1ux met %d fwdaddr %V extrtflg %ux)",
3009a747e4fSDavid du Colombier h->netmask, h->lsa.flag, Net3(h->lsa.metric),
3019a747e4fSDavid du Colombier h->lsa.fwdaddr, NetL(h->lsa.exrttag));
3029a747e4fSDavid du Colombier }
3039a747e4fSDavid du Colombier }
3049a747e4fSDavid du Colombier break;
3059a747e4fSDavid du Colombier default:
3069a747e4fSDavid du Colombier p = seprint(p, e, "Not an LS update, lstype %d ", h->lstype);
3079a747e4fSDavid du Colombier p = seprint(p, e, " %.*H", len>64?64:len, a);
3089a747e4fSDavid du Colombier break;
3099a747e4fSDavid du Colombier }
3109a747e4fSDavid du Colombier return seprint(p, e, ")");
3119a747e4fSDavid du Colombier }
3129a747e4fSDavid du Colombier
3139a747e4fSDavid du Colombier char*
seprintospflsack(char * p,char * e,void * a,int len)3149a747e4fSDavid du Colombier seprintospflsack(char *p, char *e, void *a, int len)
3159a747e4fSDavid du Colombier {
3169a747e4fSDavid du Colombier int nlsa, i;
3179a747e4fSDavid du Colombier struct OspfLSAhdr *h;
3189a747e4fSDavid du Colombier
3199a747e4fSDavid du Colombier h = (struct OspfLSAhdr *)a;
3209a747e4fSDavid du Colombier nlsa = len/sizeof(struct OspfLSAhdr);
3219a747e4fSDavid du Colombier p = seprint(p, e, "%d-%s(", nlsa, ospfpkttype(OSPFlsack));
3229a747e4fSDavid du Colombier for (i=0; i<nlsa; i++) {
3239a747e4fSDavid du Colombier p = seprint(p, e, " lsa%d(", i);
3249a747e4fSDavid du Colombier p = seprintospflsaheader(p, e, &(h[i]));
3259a747e4fSDavid du Colombier p = seprint(p, e, ")");
3269a747e4fSDavid du Colombier }
3279a747e4fSDavid du Colombier return seprint(p, e, ")");
3289a747e4fSDavid du Colombier }
3299a747e4fSDavid du Colombier
3309a747e4fSDavid du Colombier int
p_seprint(Msg * m)3319a747e4fSDavid du Colombier p_seprint(Msg *m)
3329a747e4fSDavid du Colombier {
3339a747e4fSDavid du Colombier Ospfpkt *ospf;
3349a747e4fSDavid du Colombier int len, x;
3359a747e4fSDavid du Colombier char *p, *e;
3369a747e4fSDavid du Colombier
3379a747e4fSDavid du Colombier len = m->pe - m->ps;
3389a747e4fSDavid du Colombier if(len < OSPF_HDRSIZE)
3399a747e4fSDavid du Colombier return -1;
3409a747e4fSDavid du Colombier p = m->p;
3419a747e4fSDavid du Colombier e = m->e;
3429a747e4fSDavid du Colombier
3439a747e4fSDavid du Colombier /* adjust packet size */
3449a747e4fSDavid du Colombier ospf = (Ospfpkt*)m->ps;
3459a747e4fSDavid du Colombier x = NetS(ospf->length);
3469a747e4fSDavid du Colombier if(x < len)
3479a747e4fSDavid du Colombier return -1;
3489a747e4fSDavid du Colombier x -= OSPF_HDRSIZE;
3499a747e4fSDavid du Colombier
3509a747e4fSDavid du Colombier p = seprint(p, e, "ver=%d type=%d len=%d r=%V a=%V c=%4.4ux %s ",
3519a747e4fSDavid du Colombier ospf->version, ospf->type, x,
3529a747e4fSDavid du Colombier ospf->router, ospf->area, NetS(ospf->sum),
3539a747e4fSDavid du Colombier ospfauth(ospf));
3549a747e4fSDavid du Colombier
3559a747e4fSDavid du Colombier switch (ospf->type) {
3569a747e4fSDavid du Colombier case OSPFhello:
357*2cca75a1SDavid du Colombier p = seprintospfhello(p, e, ospf->data);
3589a747e4fSDavid du Colombier break;
3599a747e4fSDavid du Colombier case OSPFdd:
3609a747e4fSDavid du Colombier p = seprintospfdatadesc(p, e, ospf->data, x);
3619a747e4fSDavid du Colombier break;
3629a747e4fSDavid du Colombier case OSPFlsrequest:
3639a747e4fSDavid du Colombier p = seprint(p, e, " %s->", ospfpkttype(ospf->type));
3649a747e4fSDavid du Colombier goto Default;
3659a747e4fSDavid du Colombier case OSPFlsupdate:
3669a747e4fSDavid du Colombier p = seprintospflsupdate(p, e, ospf->data, x);
3679a747e4fSDavid du Colombier break;
3689a747e4fSDavid du Colombier case OSPFlsack:
3699a747e4fSDavid du Colombier p = seprintospflsack(p, e, ospf->data, x);
3709a747e4fSDavid du Colombier break;
3719a747e4fSDavid du Colombier default:
3729a747e4fSDavid du Colombier Default:
3739a747e4fSDavid du Colombier p = seprint(p, e, " data=%.*H", x>64?64:x, ospf->data);
3749a747e4fSDavid du Colombier }
3759a747e4fSDavid du Colombier m->p = p;
3769a747e4fSDavid du Colombier m->pr = nil;
3779a747e4fSDavid du Colombier return 0;
3789a747e4fSDavid du Colombier }
3799a747e4fSDavid du Colombier
3809a747e4fSDavid du Colombier Proto ospf =
3819a747e4fSDavid du Colombier {
3829a747e4fSDavid du Colombier "ospf",
383*2cca75a1SDavid du Colombier nil,
384*2cca75a1SDavid du Colombier nil,
3859a747e4fSDavid du Colombier p_seprint,
3869a747e4fSDavid du Colombier nil,
3879a747e4fSDavid du Colombier nil,
388ed397113SDavid du Colombier nil,
3893ff48bf5SDavid du Colombier defaultframer,
3909a747e4fSDavid du Colombier };
391