URI:
       tppp.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tppp.c (10519B)
       ---
            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 /* PPP stuff */
            9 enum {
           10         PPP_addr=        0xff,
           11         PPP_ctl=        0x3,
           12         PPP_period=        3*1000,        /* period of retransmit process (in ms) */
           13 };
           14 
           15 /* PPP protocols */
           16 enum {
           17         PPP_ip=                0x21,                /* internet */
           18         PPP_vjctcp=        0x2d,                /* compressing van jacobson tcp */
           19         PPP_vjutcp=        0x2f,                /* uncompressing van jacobson tcp */
           20         PPP_ml=                0x3d,                /* multi link */
           21         PPP_comp=        0xfd,                /* compressed packets */
           22         PPP_ipcp=        0x8021,                /* ip control */
           23         PPP_ccp=        0x80fd,                /* compression control */
           24         PPP_passwd=        0xc023,                /* passwd authentication */
           25         PPP_lcp=        0xc021,                /* link control */
           26         PPP_lqm=        0xc025,                /* link quality monitoring */
           27         PPP_chap=        0xc223,                /* challenge/response */
           28 };
           29 
           30 /* LCP protocol (and IPCP) */
           31 
           32 
           33 typedef struct Lcppkt        Lcppkt;
           34 struct Lcppkt
           35 {
           36         uchar        code;
           37         uchar        id;
           38         uchar        len[2];
           39         uchar        data[1];
           40 };
           41 
           42 typedef struct Lcpopt        Lcpopt;
           43 struct Lcpopt
           44 {
           45         uchar        type;
           46         uchar        len;
           47         uchar        data[1];
           48 };
           49 
           50 enum
           51 {
           52         /* LCP codes */
           53         Lconfreq=        1,
           54         Lconfack=        2,
           55         Lconfnak=        3,
           56         Lconfrej=        4,
           57         Ltermreq=        5,
           58         Ltermack=        6,
           59         Lcoderej=        7,
           60         Lprotorej=        8,
           61         Lechoreq=        9,
           62         Lechoack=        10,
           63         Ldiscard=        11,
           64         Lresetreq=        14,        /* for ccp only */
           65         Lresetack=        15,        /* for ccp only */
           66 
           67         /* Lcp configure options */
           68         Omtu=                1,
           69         Octlmap=        2,
           70         Oauth=                3,
           71         Oquality=        4,
           72         Omagic=                5,
           73         Opc=                7,
           74         Oac=                8,
           75 
           76         /* authentication protocols */
           77         APmd5=                5,
           78         APmschap=        128,
           79 
           80         /* Chap codes */
           81         Cchallenge=        1,
           82         Cresponse=        2,
           83         Csuccess=        3,
           84         Cfailure=        4,
           85 
           86         /* ipcp configure options */
           87         Oipaddrs=        1,
           88         Oipcompress=        2,
           89         Oipaddr=        3,
           90         Oipdns=                129,
           91         Oipwins=        130,
           92         Oipdns2=        131,
           93         Oipwins2=        132
           94 };
           95 
           96 char *
           97 lcpcode[] = {
           98         0,
           99         "confreq",
          100         "confack",
          101         "confnak",
          102         "confrej",
          103         "termreq",
          104         "termack",
          105         "coderej",
          106         "protorej",
          107         "echoreq",
          108         "echoack",
          109         "discard",
          110         "id",
          111         "timeremain",
          112         "resetreq",
          113         "resetack"
          114 };
          115 
          116 static Mux p_mux[] =
          117 {
          118         {"ip",                PPP_ip, },
          119         {"ppp_vjctcp",        PPP_vjctcp, },
          120         {"ppp_vjutcp",        PPP_vjutcp, },
          121         {"ppp_ml",        PPP_ml, },
          122         {"ppp_comp",        PPP_comp, },
          123         {"ppp_ipcp",        PPP_ipcp, },
          124         {"ppp_ccp",        PPP_ccp, },
          125         {"ppp_passwd",        PPP_passwd, },
          126         {"ppp_lcp",        PPP_lcp, },
          127         {"ppp_lqm",        PPP_lqm, },
          128         {"ppp_chap",        PPP_chap, },
          129         {0}
          130 };
          131 
          132 enum
          133 {
          134         OOproto
          135 };
          136 
          137 static void
          138 p_compile(Filter *f)
          139 {
          140         Mux *m;
          141 
          142         for(m = p_mux; m->name != nil; m++)
          143                 if(strcmp(f->s, m->name) == 0){
          144                         f->pr = m->pr;
          145                         f->ulv = m->val;
          146                         f->subop = OOproto;
          147                         return;
          148                 }
          149 
          150         sysfatal("unknown ppp field or protocol: %s", f->s);
          151 }
          152 
          153 static int
          154 p_filter(Filter *f, Msg *m)
          155 {
          156         int proto;
          157         int len;
          158 
          159         if(f->subop != OOproto)
          160                 return 0;
          161 
          162         len = m->pe - m->ps;
          163         if(len < 3)
          164                 return -1;
          165 
          166         if(m->ps[0] == PPP_addr && m->ps[1] == PPP_ctl)
          167                 m->ps += 2;
          168 
          169         proto = *m->ps++;
          170         if((proto&1) == 0)
          171                 proto = (proto<<8) | *m->ps++;
          172 
          173         if(proto == f->ulv)
          174                 return 1;
          175 
          176         return 0;
          177 }
          178 
          179 static int
          180 p_seprint(Msg *m)
          181 {
          182         int proto;
          183         int len;
          184 
          185         len = m->pe - m->ps;
          186         if(len < 3)
          187                 return -1;
          188 
          189         if(m->ps[0] == PPP_addr && m->ps[1] == PPP_ctl)
          190                 m->ps += 2;
          191 
          192         proto = *m->ps++;
          193         if((proto&1) == 0)
          194                 proto = (proto<<8) | *m->ps++;
          195 
          196         m->p = seprint(m->p, m->e, "pr=%ud len=%d", proto, len);
          197         demux(p_mux, proto, proto, m, &dump);
          198 
          199         return 0;
          200 }
          201 
          202 static int
          203 p_seprintchap(Msg *m)
          204 {
          205         Lcppkt *lcp;
          206         char *p, *e;
          207         int len;
          208 
          209         if(m->pe-m->ps < 4)
          210                 return -1;
          211 
          212         p = m->p;
          213         e = m->e;
          214         m->pr = nil;
          215 
          216         /* resize packet */
          217         lcp = (Lcppkt*)m->ps;
          218         len = NetS(lcp->len);
          219         if(m->ps+len < m->pe)
          220                 m->pe = m->ps+len;
          221         else if(m->ps+len > m->pe)
          222                 return -1;
          223 
          224         p = seprint(p, e, "id=%d code=%d", lcp->id, lcp->code);
          225         switch(lcp->code) {
          226         default:
          227                 p = seprint(p, e, " data=%.*H", len>64?64:len, lcp->data);
          228                 break;
          229         case 1:
          230         case 2:
          231                 if(lcp->data[0] > len-4){
          232                         p = seprint(p, e, "%.*H", len-4, lcp->data);
          233                 } else {
          234                         p = seprint(p, e, " %s=", lcp->code==1?"challenge ":"response ");
          235                         p = seprint(p, e, "%.*H", lcp->data[0], lcp->data+1);
          236                         p = seprint(p, e, " name=");
          237                         p = seprint(p, e, "%.*H", len-4-lcp->data[0]-1, lcp->data+lcp->data[0]+1);
          238                 }
          239                 break;
          240         case 3:
          241         case 4:
          242                 if(len > 64)
          243                         len = 64;
          244                 p = seprint(p, e, " %s=%.*H", lcp->code==3?"success ":"failure",
          245                                 len>64?64:len, lcp->data);
          246                 break;
          247         }
          248         m->p = seprint(p, e, " len=%d", len);
          249         return 0;
          250 }
          251 
          252 static char*
          253 seprintlcpopt(char *p, char *e, void *a, int len)
          254 {
          255         Lcpopt *o;
          256         int proto, x, period;
          257         uchar *cp, *ecp;
          258 
          259         cp = a;
          260         ecp = cp+len;
          261 
          262         for(; cp < ecp; cp += o->len){
          263                 o = (Lcpopt*)cp;
          264                 if(cp + o->len > ecp || o->len == 0){
          265                         p = seprint(p, e, " bad-opt-len=%d", o->len);
          266                         return p;
          267                 }
          268 
          269                 switch(o->type){
          270                 default:
          271                         p = seprint(p, e, " (type=%d len=%d)", o->type, o->len);
          272                         break;
          273                 case Omtu:
          274                         p = seprint(p, e, " mtu=%d", NetS(o->data));
          275                         break;
          276                 case Octlmap:
          277                         p = seprint(p, e, " ctlmap=%ux", NetL(o->data));
          278                         break;
          279                 case Oauth:
          280                         proto = NetS(o->data);
          281                         switch(proto) {
          282                         default:
          283                                 p = seprint(p, e, " auth=%d", proto);
          284                                 break;
          285                         case PPP_passwd:
          286                                 p = seprint(p, e, " auth=passwd");
          287                                 break;
          288                         case PPP_chap:
          289                                 p = seprint(p, e, " (auth=chap data=%2.2ux)", o->data[2]);
          290                                 break;
          291                         }
          292                         break;
          293                 case Oquality:
          294                         proto = NetS(o->data);
          295                         switch(proto) {
          296                         default:
          297                                 p = seprint(p, e, " qproto=%d", proto);
          298                                 break;
          299                         case PPP_lqm:
          300                                 x = NetL(o->data+2)*10;
          301                                 period = (x+(PPP_period-1))/PPP_period;
          302                                 p = seprint(p, e, " (qproto=lqm period=%d)", period);
          303                                 break;
          304                         }
          305                 case Omagic:
          306                         p = seprint(p, e, " magic=%ux", NetL(o->data));
          307                         break;
          308                 case Opc:
          309                         p = seprint(p, e, " protocol-compress");
          310                         break;
          311                 case Oac:
          312                         p = seprint(p, e, " addr-compress");
          313                         break;
          314                 }
          315         }
          316         return p;
          317 }
          318 
          319 
          320 static int
          321 p_seprintlcp(Msg *m)
          322 {
          323         Lcppkt *lcp;
          324         char *p, *e;
          325         int len;
          326 
          327         if(m->pe-m->ps < 4)
          328                 return -1;
          329 
          330         p = m->p;
          331         e = m->e;
          332         m->pr = nil;
          333 
          334         lcp = (Lcppkt*)m->ps;
          335         len = NetS(lcp->len);
          336         if(m->ps+len < m->pe)
          337                 m->pe = m->ps+len;
          338         else if(m->ps+len > m->pe)
          339                 return -1;
          340 
          341         p = seprint(p, e, "id=%d code=%d", lcp->id, lcp->code);
          342         switch(lcp->code) {
          343         default:
          344                 p = seprint(p, e, " data=%.*H", len>64?64:len, lcp->data);
          345                 break;
          346         case Lconfreq:
          347         case Lconfack:
          348         case Lconfnak:
          349         case Lconfrej:
          350                 p = seprint(p, e, "=%s", lcpcode[lcp->code]);
          351                 p = seprintlcpopt(p, e, lcp->data, len-4);
          352                 break;
          353         case Ltermreq:
          354         case Ltermack:
          355         case Lcoderej:
          356         case Lprotorej:
          357         case Lechoreq:
          358         case Lechoack:
          359         case Ldiscard:
          360                 p = seprint(p, e, "=%s", lcpcode[lcp->code]);
          361                 break;
          362         }
          363         m->p = seprint(p, e, " len=%d", len);
          364         return 0;
          365 }
          366 
          367 static char*
          368 seprintipcpopt(char *p, char *e, void *a, int len)
          369 {
          370         Lcpopt *o;
          371         uchar *cp, *ecp;
          372 
          373         cp = a;
          374         ecp = cp+len;
          375 
          376         for(; cp < ecp; cp += o->len){
          377                 o = (Lcpopt*)cp;
          378                 if(cp + o->len > ecp){
          379                         p = seprint(p, e, " bad opt len %ux", o->type);
          380                         return p;
          381                 }
          382 
          383                 switch(o->type){
          384                 default:
          385                         p = seprint(p, e, " (type=%d len=%d)", o->type, o->len);
          386                         break;
          387                 case Oipaddrs:
          388                         p = seprint(p, e, " ipaddrs(deprecated)");
          389                         break;
          390                 case Oipcompress:
          391                         p = seprint(p, e, " ipcompress");
          392                         break;
          393                 case Oipaddr:
          394                         p = seprint(p, e, " ipaddr=%V", o->data);
          395                         break;
          396                 case Oipdns:
          397                         p = seprint(p, e, " dnsaddr=%V", o->data);
          398                         break;
          399                 case Oipwins:
          400                         p = seprint(p, e, " winsaddr=%V", o->data);
          401                         break;
          402                 case Oipdns2:
          403                         p = seprint(p, e, " dns2addr=%V", o->data);
          404                         break;
          405                 case Oipwins2:
          406                         p = seprint(p, e, " wins2addr=%V", o->data);
          407                         break;
          408                 }
          409         }
          410         return p;
          411 }
          412 
          413 static int
          414 p_seprintipcp(Msg *m)
          415 {
          416         Lcppkt *lcp;
          417         char *p, *e;
          418         int len;
          419 
          420         if(m->pe-m->ps < 4)
          421                 return -1;
          422 
          423         p = m->p;
          424         e = m->e;
          425         m->pr = nil;
          426 
          427         lcp = (Lcppkt*)m->ps;
          428         len = NetS(lcp->len);
          429         if(m->ps+len < m->pe)
          430                 m->pe = m->ps+len;
          431         else if(m->ps+len > m->pe)
          432                 return -1;
          433 
          434         p = seprint(p, e, "id=%d code=%d", lcp->id, lcp->code);
          435         switch(lcp->code) {
          436         default:
          437                 p = seprint(p, e, " data=%.*H", len>64?64:len, lcp->data);
          438                 break;
          439         case Lconfreq:
          440         case Lconfack:
          441         case Lconfnak:
          442         case Lconfrej:
          443                 p = seprint(p, e, "=%s", lcpcode[lcp->code]);
          444                 p = seprintipcpopt(p, e, lcp->data, len-4);
          445                 break;
          446         case Ltermreq:
          447         case Ltermack:
          448                 p = seprint(p, e, "=%s", lcpcode[lcp->code]);
          449                 break;
          450         }
          451         m->p = seprint(p, e, " len=%d", len);
          452         return 0;
          453 }
          454 
          455 static char*
          456 seprintccpopt(char *p, char *e, void *a, int len)
          457 {
          458         Lcpopt *o;
          459         uchar *cp, *ecp;
          460 
          461         cp = a;
          462         ecp = cp+len;
          463 
          464         for(; cp < ecp; cp += o->len){
          465                 o = (Lcpopt*)cp;
          466                 if(cp + o->len > ecp){
          467                         p = seprint(p, e, " bad opt len %ux", o->type);
          468                         return p;
          469                 }
          470 
          471                 switch(o->type){
          472                 default:
          473                         p = seprint(p, e, " type=%d ", o->type);
          474                         break;
          475                 case 0:
          476                         p = seprint(p, e, " OUI=(%d %.2ux%.2ux%.2ux) ", o->type,
          477                                 o->data[0], o->data[1], o->data[2]);
          478                         break;
          479                 case 17:
          480                         p = seprint(p, e, " Stac-LZS");
          481                         break;
          482                 case 18:
          483                         p = seprint(p, e, " Microsoft-PPC=%ux", NetL(o->data));
          484                         break;
          485                 }
          486         }
          487         return p;
          488 }
          489 
          490 static int
          491 p_seprintccp(Msg *m)
          492 {
          493         Lcppkt *lcp;
          494         char *p, *e;
          495         int len;
          496 
          497         if(m->pe-m->ps < 4)
          498                 return -1;
          499 
          500         p = m->p;
          501         e = m->e;
          502         m->pr = nil;
          503 
          504         lcp = (Lcppkt*)m->ps;
          505         len = NetS(lcp->len);
          506         if(m->ps+len < m->pe)
          507                 m->pe = m->ps+len;
          508         else if(m->ps+len > m->pe)
          509                 return -1;
          510 
          511         p = seprint(p, e, "id=%d code=%d", lcp->id, lcp->code);
          512         switch(lcp->code) {
          513         default:
          514                 p = seprint(p, e, " data=%.*H", len>64?64:len, lcp->data);
          515                 break;
          516         case Lconfreq:
          517         case Lconfack:
          518         case Lconfnak:
          519         case Lconfrej:
          520                 p = seprint(p, e, "=%s", lcpcode[lcp->code]);
          521                 p = seprintccpopt(p, e, lcp->data, len-4);
          522                 break;
          523         case Ltermreq:
          524         case Ltermack:
          525         case Lresetreq:
          526         case Lresetack:
          527                 p = seprint(p, e, "=%s", lcpcode[lcp->code]);
          528                 break;
          529         }
          530         m->p = seprint(p, e, " len=%d", len);
          531 
          532         return 0;
          533 }
          534 
          535 static int
          536 p_seprintcomp(Msg *m)
          537 {
          538         char compflag[5];
          539         ushort x;
          540         int i;
          541         int len;
          542 
          543         len = m->pe-m->ps;
          544         if(len < 2)
          545                 return -1;
          546 
          547         x = NetS(m->ps);
          548         m->ps += 2;
          549         i = 0;
          550         if(x & (1<<15))
          551                 compflag[i++] = 'r';
          552         if(x & (1<<14))
          553                 compflag[i++] = 'f';
          554         if(x & (1<<13))
          555                 compflag[i++] = 'c';
          556         if(x & (1<<12))
          557                 compflag[i++] = 'e';
          558         compflag[i] = 0;
          559         m->p = seprint(m->p, m->e, "flag=%s count=%.3ux", compflag, x&0xfff);
          560         m->p = seprint(m->p, m->e, " data=%.*H", len>64?64:len, m->ps);
          561         m->pr = nil;
          562         return 0;
          563 }
          564 
          565 Proto ppp =
          566 {
          567         "ppp",
          568         p_compile,
          569         p_filter,
          570         p_seprint,
          571         p_mux,
          572         "%#.4lux",
          573         nil,
          574         defaultframer
          575 };
          576 
          577 Proto ppp_ipcp =
          578 {
          579         "ppp_ipcp",
          580         p_compile,
          581         p_filter,
          582         p_seprintipcp,
          583         nil,
          584         nil,
          585         nil,
          586         defaultframer
          587 };
          588 
          589 Proto ppp_lcp =
          590 {
          591         "ppp_lcp",
          592         p_compile,
          593         p_filter,
          594         p_seprintlcp,
          595         nil,
          596         nil,
          597         nil,
          598         defaultframer
          599 };
          600 
          601 Proto ppp_ccp =
          602 {
          603         "ppp_ccp",
          604         p_compile,
          605         p_filter,
          606         p_seprintccp,
          607         nil,
          608         nil,
          609         nil,
          610         defaultframer
          611 };
          612 
          613 Proto ppp_chap =
          614 {
          615         "ppp_chap",
          616         p_compile,
          617         p_filter,
          618         p_seprintchap,
          619         nil,
          620         nil,
          621         nil,
          622         defaultframer
          623 };
          624 
          625 Proto ppp_comp =
          626 {
          627         "ppp_comp",
          628         p_compile,
          629         p_filter,
          630         p_seprintcomp,
          631         nil,
          632         nil,
          633         nil,
          634         defaultframer
          635 };