1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494 |
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/stat.h>
- #include <sys/stream.h>
- #include <sys/stropts.h>
- #include <sys/errno.h>
- #ifdef __osf__
- #include <sys/ioctl.h>
- #include <sys/cmn_err.h>
- #define queclass(mp) ((mp)->b_band & QPCTL)
- #else
- #include <sys/ioccom.h>
- #endif
- #include <sys/time.h>
- #ifdef SVR4
- #include <sys/cmn_err.h>
- #include <sys/conf.h>
- #include <sys/dlpi.h>
- #include <sys/ddi.h>
- #ifdef SOL2
- #include <sys/ksynch.h>
- #include <sys/kstat.h>
- #include <sys/sunddi.h>
- #include <sys/ethernet.h>
- #else
- #include <sys/socket.h>
- #include <sys/sockio.h>
- #include <net/if.h>
- #include <netinet/in.h>
- #endif
- #else
- #include <sys/user.h>
- #endif
- #include <net/ppp_defs.h>
- #include <net/pppio.h>
- #include "ppp_mod.h"
- #ifdef PRIOQ
- #endif
- #include <netinet/in.h> /* leave this outside of PRIOQ for htons */
- #ifdef __STDC__
- #define __P(x) x
- #else
- #define __P(x) ()
- #endif
- #ifndef ETHERTYPE_IP
- #define ETHERTYPE_IP 0x800
- #endif
- #if !defined(ETHERTYPE_IPV6)
- #define ETHERTYPE_IPV6 0x86dd
- #endif
- #if !defined(ETHERTYPE_ALLSAP) && defined(SOL2)
- #define ETHERTYPE_ALLSAP 0
- #endif
- #if !defined(PPP_ALLSAP) && defined(SOL2)
- #define PPP_ALLSAP PPP_ALLSTATIONS
- #endif
- extern time_t time;
- #ifdef SOL2
- krwlock_t ppp_lower_lock;
- #define LOCK_LOWER_W rw_enter(&ppp_lower_lock, RW_WRITER)
- #define LOCK_LOWER_R rw_enter(&ppp_lower_lock, RW_READER)
- #define TRYLOCK_LOWER_R rw_tryenter(&ppp_lower_lock, RW_READER)
- #define UNLOCK_LOWER rw_exit(&ppp_lower_lock)
- #define MT_ENTER(x) mutex_enter(x)
- #define MT_EXIT(x) mutex_exit(x)
- #else
- #define LOCK_LOWER_W 0
- #define LOCK_LOWER_R 0
- #define TRYLOCK_LOWER_R 1
- #define UNLOCK_LOWER 0
- #define MT_ENTER(x) 0
- #define MT_EXIT(x) 0
- #endif
- typedef struct upperstr {
- minor_t mn;
- struct upperstr *nextmn;
- queue_t *q;
- int flags;
- int state;
- int sap;
- int req_sap;
- struct upperstr *ppa;
- struct upperstr *next;
- uint ioc_id;
- enum NPmode npmode;
- unsigned char rblocked;
-
-
- int ppa_id;
- queue_t *lowerq;
- struct upperstr *nextppa;
- int mru;
- int mtu;
- struct pppstat stats;
- time_t last_sent;
- time_t last_recv;
- #ifdef SOL2
- kmutex_t stats_lock;
- kstat_t *kstats;
- #endif
- #ifdef LACHTCP
- int ifflags;
- char ifname[IFNAMSIZ];
- struct ifstats ifstats;
- #endif
- } upperstr_t;
- #define US_PRIV 1
- #define US_CONTROL 2
- #define US_BLOCKED 4
- #define US_LASTMOD 8
- #define US_DBGLOG 0x10
- #define US_RBLOCKED 0x20
- #if defined(SOL2)
- #if DL_CURRENT_VERSION >= 2
- #define US_PROMISC 0x40
- #endif
- #define US_RAWDATA 0x80
- #endif
- #ifdef PRIOQ
- static u_char max_band=0;
- static u_char def_band=0;
- #define IPPORT_DEFAULT 65535
- static u_short prioq_table[]= {
- 113, 53, 0,
- 22, 23, 513, 517, 518, 0,
- 514, 21, 79, 111, 0,
- 25, 109, 110, 0,
- IPPORT_DEFAULT, 0,
- 20, 70, 80, 8001, 8008, 8080, 0,
- 0 };
- #endif
- static upperstr_t *minor_devs = NULL;
- static upperstr_t *ppas = NULL;
- #ifdef SVR4
- static int pppopen __P((queue_t *, dev_t *, int, int, cred_t *));
- static int pppclose __P((queue_t *, int, cred_t *));
- #else
- static int pppopen __P((queue_t *, int, int, int));
- static int pppclose __P((queue_t *, int));
- #endif
- static int pppurput __P((queue_t *, mblk_t *));
- static int pppuwput __P((queue_t *, mblk_t *));
- static int pppursrv __P((queue_t *));
- static int pppuwsrv __P((queue_t *));
- static int ppplrput __P((queue_t *, mblk_t *));
- static int ppplwput __P((queue_t *, mblk_t *));
- static int ppplrsrv __P((queue_t *));
- static int ppplwsrv __P((queue_t *));
- #ifndef NO_DLPI
- static void dlpi_request __P((queue_t *, mblk_t *, upperstr_t *));
- static void dlpi_error __P((queue_t *, upperstr_t *, int, int, int));
- static void dlpi_ok __P((queue_t *, int));
- #endif
- static int send_data __P((mblk_t *, upperstr_t *));
- static void new_ppa __P((queue_t *, mblk_t *));
- static void attach_ppa __P((queue_t *, mblk_t *));
- static void detach_ppa __P((queue_t *, mblk_t *));
- static void detach_lower __P((queue_t *, mblk_t *));
- static void debug_dump __P((queue_t *, mblk_t *));
- static upperstr_t *find_dest __P((upperstr_t *, int));
- #if defined(SOL2)
- static upperstr_t *find_promisc __P((upperstr_t *, int));
- static mblk_t *prepend_ether __P((upperstr_t *, mblk_t *, int));
- static mblk_t *prepend_udind __P((upperstr_t *, mblk_t *, int));
- static void promisc_sendup __P((upperstr_t *, mblk_t *, int, int));
- #endif
- static int putctl2 __P((queue_t *, int, int, int));
- static int putctl4 __P((queue_t *, int, int, int));
- static int pass_packet __P((upperstr_t *ppa, mblk_t *mp, int outbound));
- #ifdef FILTER_PACKETS
- static int ip_hard_filter __P((upperstr_t *ppa, mblk_t *mp, int outbound));
- #endif
- #define PPP_ID 0xb1a6
- static struct module_info ppp_info = {
- #ifdef PRIOQ
- PPP_ID, "ppp", 0, 512, 512, 384
- #else
- PPP_ID, "ppp", 0, 512, 512, 128
- #endif
- };
- static struct qinit pppurint = {
- pppurput, pppursrv, pppopen, pppclose, NULL, &ppp_info, NULL
- };
- static struct qinit pppuwint = {
- pppuwput, pppuwsrv, NULL, NULL, NULL, &ppp_info, NULL
- };
- static struct qinit ppplrint = {
- ppplrput, ppplrsrv, NULL, NULL, NULL, &ppp_info, NULL
- };
- static struct qinit ppplwint = {
- ppplwput, ppplwsrv, NULL, NULL, NULL, &ppp_info, NULL
- };
- #ifdef LACHTCP
- extern struct ifstats *ifstats;
- int pppdevflag = 0;
- #endif
- struct streamtab pppinfo = {
- &pppurint, &pppuwint,
- &ppplrint, &ppplwint
- };
- int ppp_count;
- #ifdef SOL2
- #define INCR_IPACKETS(ppa) \
- if (ppa->kstats != 0) { \
- KSTAT_NAMED_PTR(ppa->kstats)[0].value.ul++; \
- }
- #define INCR_IERRORS(ppa) \
- if (ppa->kstats != 0) { \
- KSTAT_NAMED_PTR(ppa->kstats)[1].value.ul++; \
- }
- #define INCR_OPACKETS(ppa) \
- if (ppa->kstats != 0) { \
- KSTAT_NAMED_PTR(ppa->kstats)[2].value.ul++; \
- }
- #define INCR_OERRORS(ppa) \
- if (ppa->kstats != 0) { \
- KSTAT_NAMED_PTR(ppa->kstats)[3].value.ul++; \
- }
- #endif
- #ifdef LACHTCP
- #define INCR_IPACKETS(ppa) ppa->ifstats.ifs_ipackets++;
- #define INCR_IERRORS(ppa) ppa->ifstats.ifs_ierrors++;
- #define INCR_OPACKETS(ppa) ppa->ifstats.ifs_opackets++;
- #define INCR_OERRORS(ppa) ppa->ifstats.ifs_oerrors++;
- #endif
- static int
- #ifdef SVR4
- pppopen(q, devp, oflag, sflag, credp)
- queue_t *q;
- dev_t *devp;
- int oflag, sflag;
- cred_t *credp;
- #else
- pppopen(q, dev, oflag, sflag)
- queue_t *q;
- int dev;
- int oflag, sflag;
- #endif
- {
- upperstr_t *up;
- upperstr_t **prevp;
- minor_t mn;
- #ifdef PRIOQ
- u_short *ptr;
- u_char new_band;
- #endif
- if (q->q_ptr)
- DRV_OPEN_OK(dev);
- #ifdef PRIOQ
-
- max_band = 1;
- def_band = 0;
- ptr = prioq_table;
- while (*ptr) {
- new_band = 1;
- while (*ptr)
- if (*ptr++ == IPPORT_DEFAULT) {
- new_band = 0;
- def_band = max_band;
- }
- max_band += new_band;
- ptr++;
- }
- if (def_band)
- def_band = max_band - def_band;
- --max_band;
- #endif
- if (sflag == CLONEOPEN) {
- mn = 0;
- for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
- if (up->mn != mn)
- break;
- ++mn;
- }
- } else {
- #ifdef SVR4
- mn = getminor(*devp);
- #else
- mn = minor(dev);
- #endif
- for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
- if (up->mn >= mn)
- break;
- }
- if (up->mn == mn) {
-
- q->q_ptr = WR(q)->q_ptr = (caddr_t) up;
- DRV_OPEN_OK(dev);
- }
- }
-
- up = (upperstr_t *) ALLOC_SLEEP(sizeof(upperstr_t));
- bzero((caddr_t) up, sizeof(upperstr_t));
- if (up == 0) {
- DPRINT("pppopen: out of kernel memory\n");
- OPEN_ERROR(ENXIO);
- }
- up->nextmn = *prevp;
- *prevp = up;
- up->mn = mn;
- #ifdef SVR4
- *devp = makedevice(getmajor(*devp), mn);
- #endif
- up->q = q;
- if (NOTSUSER() == 0)
- up->flags |= US_PRIV;
- #ifndef NO_DLPI
- up->state = DL_UNATTACHED;
- #endif
- #ifdef LACHTCP
- up->ifflags = IFF_UP | IFF_POINTOPOINT;
- #endif
- up->sap = -1;
- up->last_sent = up->last_recv = time;
- up->npmode = NPMODE_DROP;
- q->q_ptr = (caddr_t) up;
- WR(q)->q_ptr = (caddr_t) up;
- noenable(WR(q));
- #ifdef SOL2
- mutex_init(&up->stats_lock, NULL, MUTEX_DRIVER, NULL);
- #endif
- ++ppp_count;
- qprocson(q);
- DRV_OPEN_OK(makedev(major(dev), mn));
- }
- static int
- #ifdef SVR4
- pppclose(q, flag, credp)
- queue_t *q;
- int flag;
- cred_t *credp;
- #else
- pppclose(q, flag)
- queue_t *q;
- int flag;
- #endif
- {
- upperstr_t *up, **upp;
- upperstr_t *as, *asnext;
- upperstr_t **prevp;
- qprocsoff(q);
- up = (upperstr_t *) q->q_ptr;
- if (up == 0) {
- DPRINT("pppclose: q_ptr = 0\n");
- return 0;
- }
- if (up->flags & US_DBGLOG)
- DPRINT2("ppp/%d: close, flags=%x\n", up->mn, up->flags);
- if (up->flags & US_CONTROL) {
- #ifdef LACHTCP
- struct ifstats *ifp, *pifp;
- #endif
- if (up->lowerq != 0) {
-
- DPRINT1("ppp%d: lower stream still connected on close?\n",
- up->mn);
- LOCK_LOWER_W;
- up->lowerq->q_ptr = 0;
- RD(up->lowerq)->q_ptr = 0;
- up->lowerq = 0;
- UNLOCK_LOWER;
- }
-
- for (as = up->next; as != 0; as = asnext) {
- asnext = as->next;
- as->next = 0;
- as->ppa = 0;
- if (as->flags & US_BLOCKED) {
- as->flags &= ~US_BLOCKED;
- flushq(WR(as->q), FLUSHDATA);
- }
- }
- for (upp = &ppas; *upp != 0; upp = &(*upp)->nextppa)
- if (*upp == up) {
- *upp = up->nextppa;
- break;
- }
- #ifdef LACHTCP
-
- for (ifp = ifstats, pifp = 0; ifp; ifp = ifp->ifs_next) {
- if (ifp == &up->ifstats) {
- if (pifp)
- pifp->ifs_next = ifp->ifs_next;
- else
- ifstats = ifp->ifs_next;
- break;
- }
- pifp = ifp;
- }
- #endif
- } else {
-
- if ((as = up->ppa) != 0) {
- for (; as->next != 0; as = as->next)
- if (as->next == up) {
- as->next = up->next;
- break;
- }
- }
- }
- #ifdef SOL2
- if (up->kstats)
- kstat_delete(up->kstats);
- mutex_destroy(&up->stats_lock);
- #endif
- q->q_ptr = NULL;
- WR(q)->q_ptr = NULL;
- for (prevp = &minor_devs; *prevp != 0; prevp = &(*prevp)->nextmn) {
- if (*prevp == up) {
- *prevp = up->nextmn;
- break;
- }
- }
- FREE(up, sizeof(upperstr_t));
- --ppp_count;
- return 0;
- }
- static int
- pppuwput(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- upperstr_t *us, *ppa, *nps;
- struct iocblk *iop;
- struct linkblk *lb;
- #ifdef LACHTCP
- struct ifreq *ifr;
- int i;
- #endif
- queue_t *lq;
- int error, n, sap;
- mblk_t *mq;
- struct ppp_idle *pip;
- #ifdef PRIOQ
- queue_t *tlq;
- #endif
- #ifdef NO_DLPI
- upperstr_t *os;
- #endif
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("pppuwput: q_ptr = 0!\n");
- return 0;
- }
- if (mp == 0) {
- DPRINT1("pppuwput/%d: mp = 0!\n", us->mn);
- return 0;
- }
- if (mp->b_datap == 0) {
- DPRINT1("pppuwput/%d: mp->b_datap = 0!\n", us->mn);
- return 0;
- }
- switch (mp->b_datap->db_type) {
- #ifndef NO_DLPI
- case M_PCPROTO:
- case M_PROTO:
- dlpi_request(q, mp, us);
- break;
- #endif
- case M_DATA:
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: uwput M_DATA len=%d flags=%x\n",
- us->mn, msgdsize(mp), us->flags);
- if (us->ppa == 0 || msgdsize(mp) > us->ppa->mtu + PPP_HDRLEN
- #ifndef NO_DLPI
- || (us->flags & US_CONTROL) == 0
- #endif
- ) {
- DPRINT1("pppuwput: junk data len=%d\n", msgdsize(mp));
- freemsg(mp);
- break;
- }
- #ifdef NO_DLPI
- if ((us->flags & US_CONTROL) == 0 && !pass_packet(us, mp, 1))
- break;
- #endif
- if (!send_data(mp, us))
- putq(q, mp);
- break;
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- error = EINVAL;
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: ioctl %x count=%d\n",
- us->mn, iop->ioc_cmd, iop->ioc_count);
- switch (iop->ioc_cmd) {
- #if defined(SOL2)
- case DLIOCRAW:
- us->flags |= US_RAWDATA;
- error = 0;
- break;
- #endif
- case I_LINK:
- if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl I_LINK b_cont = 0!\n", us->mn);
- break;
- }
- lb = (struct linkblk *) mp->b_cont->b_rptr;
- lq = lb->l_qbot;
- if (lq == 0) {
- DPRINT1("pppuwput/%d: ioctl I_LINK l_qbot = 0!\n", us->mn);
- break;
- }
- LOCK_LOWER_W;
- us->lowerq = lq;
- lq->q_ptr = (caddr_t) q;
- RD(lq)->q_ptr = (caddr_t) us->q;
- UNLOCK_LOWER;
- iop->ioc_count = 0;
- error = 0;
- us->flags &= ~US_LASTMOD;
-
- qenable(q);
-
- putctl2(lq, M_CTL, PPPCTL_UNIT, us->ppa_id);
- putctl4(lq, M_CTL, PPPCTL_MRU, us->mru);
- putctl4(lq, M_CTL, PPPCTL_MTU, us->mtu);
- #ifdef PRIOQ
-
- freezestr(lq);
- for (tlq = lq; tlq->q_next != NULL; tlq = tlq->q_next)
- ;
- strqset(tlq, QHIWAT, 0, 256);
- strqset(tlq, QLOWAT, 0, 128);
- unfreezestr(lq);
- #endif
- break;
- case I_UNLINK:
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl I_UNLINK b_cont = 0!\n", us->mn);
- break;
- }
- lb = (struct linkblk *) mp->b_cont->b_rptr;
- #if DEBUG
- if (us->lowerq != lb->l_qbot) {
- DPRINT2("ppp unlink: lowerq=%x qbot=%x\n",
- us->lowerq, lb->l_qbot);
- break;
- }
- #endif
- iop->ioc_count = 0;
- qwriter(q, mp, detach_lower, PERIM_OUTER);
- error = -1;
- break;
- case PPPIO_NEWPPA:
- if (us->flags & US_CONTROL)
- break;
- if ((us->flags & US_PRIV) == 0) {
- error = EPERM;
- break;
- }
-
- if ((mq = mp->b_cont) == 0
- || mq->b_datap->db_lim - mq->b_rptr < sizeof(int)) {
- mq = allocb(sizeof(int), BPRI_HI);
- if (mq == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = mq;
- mq->b_cont = 0;
- }
- iop->ioc_count = sizeof(int);
- mq->b_wptr = mq->b_rptr + sizeof(int);
- qwriter(q, mp, new_ppa, PERIM_OUTER);
- error = -1;
- break;
- case PPPIO_ATTACH:
-
- if (iop->ioc_count != sizeof(int) || us->ppa != 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_ATTACH b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
- if (ppa->ppa_id == n)
- break;
- if (ppa == 0)
- break;
- us->ppa = ppa;
- iop->ioc_count = 0;
- qwriter(q, mp, attach_ppa, PERIM_OUTER);
- error = -1;
- break;
- #ifdef NO_DLPI
- case PPPIO_BIND:
-
- if (iop->ioc_count != sizeof(int) || us->ppa == 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_BIND b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
-
- if (n < 0x21 || n > 0x3fff || (n & 0x101) != 1)
- break;
-
- for (os = us->ppa; os != 0; os = os->next)
- if (os->sap == n)
- break;
- if (os != 0)
- break;
- us->sap = n;
- iop->ioc_count = 0;
- error = 0;
- break;
- #endif
- case PPPIO_MRU:
- if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_MRU b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- if (n <= 0 || n > PPP_MAXMRU)
- break;
- if (n < PPP_MRU)
- n = PPP_MRU;
- us->mru = n;
- if (us->lowerq)
- putctl4(us->lowerq, M_CTL, PPPCTL_MRU, n);
- error = 0;
- iop->ioc_count = 0;
- break;
- case PPPIO_MTU:
- if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_MTU b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- if (n <= 0 || n > PPP_MAXMTU)
- break;
- us->mtu = n;
- #ifdef LACHTCP
-
- us->ifstats.ifs_mtu = n;
- #endif
- if (us->lowerq)
- putctl4(us->lowerq, M_CTL, PPPCTL_MTU, n);
- error = 0;
- iop->ioc_count = 0;
- break;
- case PPPIO_LASTMOD:
- us->flags |= US_LASTMOD;
- error = 0;
- break;
- case PPPIO_DEBUG:
- if (iop->ioc_count != sizeof(int))
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_DEBUG b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- if (n == PPPDBG_DUMP + PPPDBG_DRIVER) {
- qwriter(q, NULL, debug_dump, PERIM_OUTER);
- iop->ioc_count = 0;
- error = -1;
- } else if (n == PPPDBG_LOG + PPPDBG_DRIVER) {
- DPRINT1("ppp/%d: debug log enabled\n", us->mn);
- us->flags |= US_DBGLOG;
- iop->ioc_count = 0;
- error = 0;
- } else {
- if (us->ppa == 0 || us->ppa->lowerq == 0)
- break;
- putnext(us->ppa->lowerq, mp);
- error = -1;
- }
- break;
- case PPPIO_NPMODE:
- if (iop->ioc_count != 2 * sizeof(int))
- break;
- if ((us->flags & US_CONTROL) == 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_NPMODE b_cont = 0!\n", us->mn);
- break;
- }
- sap = ((int *)mp->b_cont->b_rptr)[0];
- for (nps = us->next; nps != 0; nps = nps->next) {
- if (us->flags & US_DBGLOG)
- DPRINT2("us = 0x%x, us->next->sap = 0x%x\n", nps, nps->sap);
- if (nps->sap == sap)
- break;
- }
- if (nps == 0) {
- if (us->flags & US_DBGLOG)
- DPRINT2("ppp/%d: no stream for sap %x\n", us->mn, sap);
- break;
- }
-
- nps->npmode = (enum NPmode) ((int *)mp->b_cont->b_rptr)[1];
- if (nps->npmode != NPMODE_QUEUE && (nps->flags & US_BLOCKED) != 0)
- qenable(WR(nps->q));
- iop->ioc_count = 0;
- error = 0;
- break;
- case PPPIO_GIDLE:
- if ((ppa = us->ppa) == 0)
- break;
- mq = allocb(sizeof(struct ppp_idle), BPRI_HI);
- if (mq == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = mq;
- mq->b_cont = 0;
- pip = (struct ppp_idle *) mq->b_wptr;
- pip->xmit_idle = time - ppa->last_sent;
- pip->recv_idle = time - ppa->last_recv;
- mq->b_wptr += sizeof(struct ppp_idle);
- iop->ioc_count = sizeof(struct ppp_idle);
- error = 0;
- break;
- #ifdef LACHTCP
- case SIOCSIFNAME:
-
- if (iop->ioc_count != sizeof(struct ifreq) || us->ppa == 0)
- break;
- ifr = (struct ifreq *)mp->b_cont->b_rptr;
-
- for (i = 0; i < IFNAMSIZ; i++) {
- if (ifr->ifr_name[i] == 0 ||
- (ifr->ifr_name[i] >= '0' &&
- ifr->ifr_name[i] <= '9'))
- break;
- else
- us->ifname[i] = ifr->ifr_name[i];
- }
- us->ifname[i] = 0;
-
- for (n = 0; i < IFNAMSIZ; i++) {
- if (ifr->ifr_name[i] == 0) {
- break;
- }
- else {
- n = n * 10 + ifr->ifr_name[i] - '0';
- }
- }
-
- if (us->ppa->ppa_id != n)
- break;
- ppa = us->ppa;
-
- strncpy (ppa->ifname, us->ifname, IFNAMSIZ);
- ppa->ifstats.ifs_name = ppa->ifname;
- ppa->ifstats.ifs_unit = n;
- ppa->ifstats.ifs_active = us->state != DL_UNBOUND;
- ppa->ifstats.ifs_mtu = ppa->mtu;
-
- ppa->ifstats.ifs_next = ifstats;
- ifstats = &ppa->ifstats;
- iop->ioc_count = 0;
- error = 0;
- break;
- case SIOCGIFFLAGS:
- if (!(us->flags & US_CONTROL)) {
- if (us->ppa)
- us = us->ppa;
- else
- break;
- }
- ((struct iocblk_in *)iop)->ioc_ifflags = us->ifflags;
- error = 0;
- break;
- case SIOCSIFFLAGS:
- if (!(us->flags & US_CONTROL)) {
- if (us->ppa)
- us = us->ppa;
- else
- break;
- }
- us->ifflags = ((struct iocblk_in *)iop)->ioc_ifflags;
- error = 0;
- break;
- case SIOCSIFADDR:
- if (!(us->flags & US_CONTROL)) {
- if (us->ppa)
- us = us->ppa;
- else
- break;
- }
- us->ifflags |= IFF_RUNNING;
- ((struct iocblk_in *)iop)->ioc_ifflags |= IFF_RUNNING;
- error = 0;
- break;
- case SIOCSIFMTU:
-
- if ((mq = allocb(sizeof(dl_info_req_t), BPRI_HI)) == 0)
- break;
- ((union DL_primitives *)mq->b_rptr)->dl_primitive = DL_INFO_REQ;
- mq->b_wptr = mq->b_rptr + sizeof(dl_info_req_t);
- dlpi_request(q, mq, us);
- error = 0;
- break;
- case SIOCGIFNETMASK:
- case SIOCSIFNETMASK:
- case SIOCGIFADDR:
- case SIOCGIFDSTADDR:
- case SIOCSIFDSTADDR:
- case SIOCGIFMETRIC:
- error = 0;
- break;
- #endif
- default:
- if (us->ppa == 0 || us->ppa->lowerq == 0)
- break;
- us->ioc_id = iop->ioc_id;
- error = -1;
- switch (iop->ioc_cmd) {
- case PPPIO_GETSTAT:
- case PPPIO_GETCSTAT:
- if (us->flags & US_LASTMOD) {
- error = EINVAL;
- break;
- }
- putnext(us->ppa->lowerq, mp);
- break;
- default:
- if (us->flags & US_PRIV)
- putnext(us->ppa->lowerq, mp);
- else {
- DPRINT1("ppp ioctl %x rejected\n", iop->ioc_cmd);
- error = EPERM;
- }
- break;
- }
- break;
- }
- if (error > 0) {
- iop->ioc_error = error;
- mp->b_datap->db_type = M_IOCNAK;
- qreply(q, mp);
- } else if (error == 0) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- }
- break;
- case M_FLUSH:
- if (us->flags & US_DBGLOG)
- DPRINT2("ppp/%d: flush %x\n", us->mn, *mp->b_rptr);
- if (*mp->b_rptr & FLUSHW)
- flushq(q, FLUSHDATA);
- if (*mp->b_rptr & FLUSHR) {
- *mp->b_rptr &= ~FLUSHW;
- qreply(q, mp);
- } else
- freemsg(mp);
- break;
- default:
- freemsg(mp);
- break;
- }
- return 0;
- }
- #ifndef NO_DLPI
- static void
- dlpi_request(q, mp, us)
- queue_t *q;
- mblk_t *mp;
- upperstr_t *us;
- {
- union DL_primitives *d = (union DL_primitives *) mp->b_rptr;
- int size = mp->b_wptr - mp->b_rptr;
- mblk_t *reply, *np;
- upperstr_t *ppa, *os;
- int sap, len;
- dl_info_ack_t *info;
- dl_bind_ack_t *ackp;
- #if DL_CURRENT_VERSION >= 2
- dl_phys_addr_ack_t *paddrack;
- static struct ether_addr eaddr = {0};
- #endif
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: dlpi prim %x len=%d\n", us->mn,
- d->dl_primitive, size);
- switch (d->dl_primitive) {
- case DL_INFO_REQ:
- if (size < sizeof(dl_info_req_t))
- goto badprim;
- if ((reply = allocb(sizeof(dl_info_ack_t), BPRI_HI)) == 0)
- break;
- reply->b_datap->db_type = M_PCPROTO;
- info = (dl_info_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_info_ack_t);
- bzero((caddr_t) info, sizeof(dl_info_ack_t));
- info->dl_primitive = DL_INFO_ACK;
- info->dl_max_sdu = us->ppa? us->ppa->mtu: PPP_MAXMTU;
- info->dl_min_sdu = 1;
- info->dl_addr_length = sizeof(uint);
- info->dl_mac_type = DL_ETHER;
- info->dl_current_state = us->state;
- info->dl_service_mode = DL_CLDLS;
- info->dl_provider_style = DL_STYLE2;
- #if DL_CURRENT_VERSION >= 2
- info->dl_sap_length = sizeof(uint);
- info->dl_version = DL_CURRENT_VERSION;
- #endif
- qreply(q, reply);
- break;
- case DL_ATTACH_REQ:
- if (size < sizeof(dl_attach_req_t))
- goto badprim;
- if (us->state != DL_UNATTACHED || us->ppa != 0) {
- dlpi_error(q, us, DL_ATTACH_REQ, DL_OUTSTATE, 0);
- break;
- }
- for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
- if (ppa->ppa_id == d->attach_req.dl_ppa)
- break;
- if (ppa == 0) {
- dlpi_error(q, us, DL_ATTACH_REQ, DL_BADPPA, 0);
- break;
- }
- us->ppa = ppa;
- qwriter(q, mp, attach_ppa, PERIM_OUTER);
- return;
- case DL_DETACH_REQ:
- if (size < sizeof(dl_detach_req_t))
- goto badprim;
- if (us->state != DL_UNBOUND || us->ppa == 0) {
- dlpi_error(q, us, DL_DETACH_REQ, DL_OUTSTATE, 0);
- break;
- }
- qwriter(q, mp, detach_ppa, PERIM_OUTER);
- return;
- case DL_BIND_REQ:
- if (size < sizeof(dl_bind_req_t))
- goto badprim;
- if (us->state != DL_UNBOUND || us->ppa == 0) {
- dlpi_error(q, us, DL_BIND_REQ, DL_OUTSTATE, 0);
- break;
- }
- #if 0
-
- if (d->bind_req.dl_service_mode != DL_CLDLS) {
- dlpi_error(q, us, DL_BIND_REQ, DL_UNSUPPORTED, 0);
- break;
- }
- #endif
-
- sap = d->bind_req.dl_sap;
- us->req_sap = sap;
- #if defined(SOL2)
- if (us->flags & US_DBGLOG)
- DPRINT2("DL_BIND_REQ: ip gives sap = 0x%x, us = 0x%x", sap, us);
- if (sap == ETHERTYPE_IP)
- sap = PPP_IP;
- else if (sap == ETHERTYPE_IPV6)
- sap = PPP_IPV6;
- else if (sap == ETHERTYPE_ALLSAP)
- sap = PPP_ALLSAP;
- else {
- DPRINT2("DL_BIND_REQ: unrecognized sap = 0x%x, us = 0x%x", sap, us);
- dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);
- break;
- }
- #else
- if (sap == ETHERTYPE_IP)
- sap = PPP_IP;
- if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
- dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);
- break;
- }
- #endif
-
- for (os = us->ppa; os != 0; os = os->next)
- if (os->sap == sap)
- break;
- if (os != 0) {
- dlpi_error(q, us, DL_BIND_REQ, DL_NOADDR, 0);
- break;
- }
- us->sap = sap;
- us->state = DL_IDLE;
- if ((reply = allocb(sizeof(dl_bind_ack_t) + sizeof(uint),
- BPRI_HI)) == 0)
- break;
- ackp = (dl_bind_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_bind_ack_t) + sizeof(uint);
- reply->b_datap->db_type = M_PCPROTO;
- bzero((caddr_t) ackp, sizeof(dl_bind_ack_t));
- ackp->dl_primitive = DL_BIND_ACK;
- ackp->dl_sap = sap;
- ackp->dl_addr_length = sizeof(uint);
- ackp->dl_addr_offset = sizeof(dl_bind_ack_t);
- *(uint *)(ackp+1) = sap;
- qreply(q, reply);
- break;
- case DL_UNBIND_REQ:
- if (size < sizeof(dl_unbind_req_t))
- goto badprim;
- if (us->state != DL_IDLE) {
- dlpi_error(q, us, DL_UNBIND_REQ, DL_OUTSTATE, 0);
- break;
- }
- us->sap = -1;
- us->state = DL_UNBOUND;
- #ifdef LACHTCP
- us->ppa->ifstats.ifs_active = 0;
- #endif
- dlpi_ok(q, DL_UNBIND_REQ);
- break;
- case DL_UNITDATA_REQ:
- if (size < sizeof(dl_unitdata_req_t))
- goto badprim;
- if (us->state != DL_IDLE) {
- dlpi_error(q, us, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
- break;
- }
- if ((ppa = us->ppa) == 0) {
- cmn_err(CE_CONT, "ppp: in state dl_idle but ppa == 0?\n");
- break;
- }
- len = mp->b_cont == 0? 0: msgdsize(mp->b_cont);
- if (len > ppa->mtu) {
- DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu);
- break;
- }
- #if defined(SOL2)
-
- if (mp->b_cont)
- promisc_sendup(ppa, mp->b_cont, us->sap, 0);
- #endif
- mp->b_band = 0;
- #ifdef PRIOQ
-
- if (mp->b_datap->db_type == M_PROTO && us->sap == PPP_IP
- && mp->b_cont != 0) {
- u_char *bb, *tlh;
- int iphlen, len;
- u_short *ptr;
- u_char band_unset, cur_band, syn;
- u_short s_port, d_port;
- bb = mp->b_cont->b_rptr;
- len = mp->b_cont->b_wptr - mp->b_cont->b_rptr;
- syn = 0;
- s_port = IPPORT_DEFAULT;
- d_port = IPPORT_DEFAULT;
- if (len >= 20) {
- iphlen = (bb[0] & 0x0f) * 4;
- tlh = bb + iphlen;
- len -= iphlen;
- switch (bb[9]) {
- case IPPROTO_TCP:
- if (len >= 20) {
- s_port = (tlh[0] << 8) + tlh[1];
- d_port = (tlh[2] << 8) + tlh[3];
- syn = tlh[13] & 0x02;
- }
- break;
- case IPPROTO_UDP:
- if (len >= 8) {
- s_port = (tlh[0] << 8) + tlh[1];
- d_port = (tlh[2] << 8) + tlh[3];
- }
- break;
- }
- }
-
- ptr = prioq_table;
- cur_band = max_band;
- band_unset = 1;
- while (*ptr) {
- while (*ptr && band_unset)
- if (s_port == *ptr || d_port == *ptr++) {
- mp->b_band = cur_band;
- band_unset = 0;
- break;
- }
- ptr++;
- cur_band--;
- }
- if (band_unset)
- mp->b_band = def_band;
-
- if (syn)
- mp->b_band++;
- }
- #endif
-
- if (mp->b_datap->db_ref > 1) {
- np = allocb(PPP_HDRLEN, BPRI_HI);
- if (np == 0)
- break;
- np->b_cont = mp->b_cont;
- mp->b_cont = 0;
- freeb(mp);
- mp = np;
- } else
- mp->b_datap->db_type = M_DATA;
-
- mp->b_wptr = mp->b_rptr + PPP_HDRLEN;
- mp->b_rptr[0] = PPP_ALLSTATIONS;
- mp->b_rptr[1] = PPP_UI;
- mp->b_rptr[2] = us->sap >> 8;
- mp->b_rptr[3] = us->sap;
- if (pass_packet(us, mp, 1)) {
- if (!send_data(mp, us))
- putq(q, mp);
- }
- return;
- #if DL_CURRENT_VERSION >= 2
- case DL_PHYS_ADDR_REQ:
- if (size < sizeof(dl_phys_addr_req_t))
- goto badprim;
-
- if ((reply = allocb(sizeof(dl_phys_addr_ack_t)+ETHERADDRL,
- BPRI_HI)) == 0)
- break;
- reply->b_datap->db_type = M_PCPROTO;
- paddrack = (dl_phys_addr_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_phys_addr_ack_t);
- bzero((caddr_t) paddrack, sizeof(dl_phys_addr_ack_t)+ETHERADDRL);
- paddrack->dl_primitive = DL_PHYS_ADDR_ACK;
- paddrack->dl_addr_length = ETHERADDRL;
- paddrack->dl_addr_offset = sizeof(dl_phys_addr_ack_t);
- bcopy(&eaddr, reply->b_wptr, ETHERADDRL);
- reply->b_wptr += ETHERADDRL;
- qreply(q, reply);
- break;
- #if defined(SOL2)
- case DL_PROMISCON_REQ:
- if (size < sizeof(dl_promiscon_req_t))
- goto badprim;
- us->flags |= US_PROMISC;
- dlpi_ok(q, DL_PROMISCON_REQ);
- break;
- case DL_PROMISCOFF_REQ:
- if (size < sizeof(dl_promiscoff_req_t))
- goto badprim;
- us->flags &= ~US_PROMISC;
- dlpi_ok(q, DL_PROMISCOFF_REQ);
- break;
- #else
- case DL_PROMISCON_REQ:
- case DL_PROMISCOFF_REQ:
- #endif
- #endif
- #if DL_CURRENT_VERSION >= 2
- case DL_SET_PHYS_ADDR_REQ:
- case DL_SUBS_BIND_REQ:
- case DL_SUBS_UNBIND_REQ:
- case DL_ENABMULTI_REQ:
- case DL_DISABMULTI_REQ:
- case DL_XID_REQ:
- case DL_TEST_REQ:
- case DL_REPLY_UPDATE_REQ:
- case DL_REPLY_REQ:
- case DL_DATA_ACK_REQ:
- #endif
- case DL_CONNECT_REQ:
- case DL_TOKEN_REQ:
- dlpi_error(q, us, d->dl_primitive, DL_NOTSUPPORTED, 0);
- break;
- case DL_CONNECT_RES:
- case DL_DISCONNECT_REQ:
- case DL_RESET_REQ:
- case DL_RESET_RES:
- dlpi_error(q, us, d->dl_primitive, DL_OUTSTATE, 0);
- break;
- case DL_UDQOS_REQ:
- dlpi_error(q, us, d->dl_primitive, DL_BADQOSTYPE, 0);
- break;
- #if DL_CURRENT_VERSION >= 2
- case DL_TEST_RES:
- case DL_XID_RES:
- break;
- #endif
- default:
- cmn_err(CE_CONT, "ppp: unknown dlpi prim 0x%x\n", d->dl_primitive);
-
- badprim:
- dlpi_error(q, us, d->dl_primitive, DL_BADPRIM, 0);
- break;
- }
- freemsg(mp);
- }
- static void
- dlpi_error(q, us, prim, err, uerr)
- queue_t *q;
- upperstr_t *us;
- int prim, err, uerr;
- {
- mblk_t *reply;
- dl_error_ack_t *errp;
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: dlpi error, prim=%x, err=%x\n", us->mn, prim, err);
- reply = allocb(sizeof(dl_error_ack_t), BPRI_HI);
- if (reply == 0)
- return;
- reply->b_datap->db_type = M_PCPROTO;
- errp = (dl_error_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_error_ack_t);
- errp->dl_primitive = DL_ERROR_ACK;
- errp->dl_error_primitive = prim;
- errp->dl_errno = err;
- errp->dl_unix_errno = uerr;
- qreply(q, reply);
- }
- static void
- dlpi_ok(q, prim)
- queue_t *q;
- int prim;
- {
- mblk_t *reply;
- dl_ok_ack_t *okp;
- reply = allocb(sizeof(dl_ok_ack_t), BPRI_HI);
- if (reply == 0)
- return;
- reply->b_datap->db_type = M_PCPROTO;
- okp = (dl_ok_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_ok_ack_t);
- okp->dl_primitive = DL_OK_ACK;
- okp->dl_correct_primitive = prim;
- qreply(q, reply);
- }
- #endif
- static int
- pass_packet(us, mp, outbound)
- upperstr_t *us;
- mblk_t *mp;
- int outbound;
- {
- int pass;
- upperstr_t *ppa;
- if ((ppa = us->ppa) == 0) {
- freemsg(mp);
- return 0;
- }
- #ifdef FILTER_PACKETS
- pass = ip_hard_filter(us, mp, outbound);
- #else
-
- pass = 1;
- #endif
- if (pass < 0) {
-
- if (ppa->lowerq == 0) {
- freemsg(mp);
- return 0;
- }
- pass = 1;
- } else if (pass) {
- if (outbound)
- ppa->last_sent = time;
- else
- ppa->last_recv = time;
- }
- return pass;
- }
- static int
- send_data(mp, us)
- mblk_t *mp;
- upperstr_t *us;
- {
- upperstr_t *ppa;
- if ((us->flags & US_BLOCKED) || us->npmode == NPMODE_QUEUE)
- return 0;
- ppa = us->ppa;
- if (ppa == 0 || us->npmode == NPMODE_DROP || us->npmode == NPMODE_ERROR) {
- if (us->flags & US_DBGLOG)
- DPRINT2("ppp/%d: dropping pkt (npmode=%d)\n", us->mn, us->npmode);
- freemsg(mp);
- return 1;
- }
- if (ppa->lowerq == 0) {
-
- if (bcanputnext(ppa->q, mp->b_band)) {
-
- mblk_t *np = copymsg(mp);
- freemsg(mp);
- if (np != 0)
- putnext(ppa->q, np);
- return 1;
- }
- } else {
- if (bcanputnext(ppa->lowerq, mp->b_band)) {
- MT_ENTER(&ppa->stats_lock);
- ppa->stats.ppp_opackets++;
- ppa->stats.ppp_obytes += msgdsize(mp);
- #ifdef INCR_OPACKETS
- INCR_OPACKETS(ppa);
- #endif
- MT_EXIT(&ppa->stats_lock);
-
- putnext(ppa->lowerq, mp);
- return 1;
- }
- }
- us->flags |= US_BLOCKED;
- return 0;
- }
- static void
- new_ppa(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- upperstr_t *us, *up, **usp;
- int ppa_id;
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("new_ppa: q_ptr = 0!\n");
- return;
- }
- usp = &ppas;
- ppa_id = 0;
- while ((up = *usp) != 0 && ppa_id == up->ppa_id) {
- ++ppa_id;
- usp = &up->nextppa;
- }
- us->ppa_id = ppa_id;
- us->ppa = us;
- us->next = 0;
- us->nextppa = *usp;
- *usp = us;
- us->flags |= US_CONTROL;
- us->npmode = NPMODE_PASS;
- us->mtu = PPP_MTU;
- us->mru = PPP_MRU;
- #ifdef SOL2
-
- if (us->kstats == 0) {
- char unit[32];
- sprintf(unit, "ppp%d", us->ppa->ppa_id);
- us->kstats = kstat_create("ppp", us->ppa->ppa_id, unit,
- "net", KSTAT_TYPE_NAMED, 4, 0);
- if (us->kstats != 0) {
- kstat_named_t *kn = KSTAT_NAMED_PTR(us->kstats);
- strcpy(kn[0].name, "ipackets");
- kn[0].data_type = KSTAT_DATA_ULONG;
- strcpy(kn[1].name, "ierrors");
- kn[1].data_type = KSTAT_DATA_ULONG;
- strcpy(kn[2].name, "opackets");
- kn[2].data_type = KSTAT_DATA_ULONG;
- strcpy(kn[3].name, "oerrors");
- kn[3].data_type = KSTAT_DATA_ULONG;
- kstat_install(us->kstats);
- }
- }
- #endif
- *(int *)mp->b_cont->b_rptr = ppa_id;
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- }
- static void
- attach_ppa(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- upperstr_t *us, *t;
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("attach_ppa: q_ptr = 0!\n");
- return;
- }
- #ifndef NO_DLPI
- us->state = DL_UNBOUND;
- #endif
- for (t = us->ppa; t->next != 0; t = t->next)
- ;
- t->next = us;
- us->next = 0;
- if (mp->b_datap->db_type == M_IOCTL) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- } else {
- #ifndef NO_DLPI
- dlpi_ok(q, DL_ATTACH_REQ);
- #endif
- }
- }
- static void
- detach_ppa(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- upperstr_t *us, *t;
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("detach_ppa: q_ptr = 0!\n");
- return;
- }
- for (t = us->ppa; t->next != 0; t = t->next)
- if (t->next == us) {
- t->next = us->next;
- break;
- }
- us->next = 0;
- us->ppa = 0;
- #ifndef NO_DLPI
- us->state = DL_UNATTACHED;
- dlpi_ok(q, DL_DETACH_REQ);
- #endif
- }
- static void
- detach_lower(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- upperstr_t *us;
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("detach_lower: q_ptr = 0!\n");
- return;
- }
- LOCK_LOWER_W;
- us->lowerq->q_ptr = 0;
- RD(us->lowerq)->q_ptr = 0;
- us->lowerq = 0;
- UNLOCK_LOWER;
-
- qenable(us->q);
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- }
- static int
- pppuwsrv(q)
- queue_t *q;
- {
- upperstr_t *us, *as;
- mblk_t *mp;
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("pppuwsrv: q_ptr = 0!\n");
- return 0;
- }
-
- if (us->flags & US_CONTROL) {
- for (as = us->next; as != 0; as = as->next)
- qenable(WR(as->q));
- }
-
- us->flags &= ~US_BLOCKED;
- while ((mp = getq(q)) != 0) {
- if (!send_data(mp, us)) {
- putbq(q, mp);
- break;
- }
- }
- return 0;
- }
- static int
- ppplwput(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- putnext(q, mp);
- return 0;
- }
- static int
- ppplwsrv(q)
- queue_t *q;
- {
- queue_t *uq;
-
- LOCK_LOWER_R;
- uq = (queue_t *) q->q_ptr;
- if (uq != 0)
- qenable(uq);
- UNLOCK_LOWER;
- return 0;
- }
- static int
- pppurput(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- upperstr_t *ppa, *us;
- int proto, len;
- struct iocblk *iop;
- ppa = (upperstr_t *) q->q_ptr;
- if (ppa == 0) {
- DPRINT("pppurput: q_ptr = 0!\n");
- return 0;
- }
- switch (mp->b_datap->db_type) {
- case M_CTL:
- MT_ENTER(&ppa->stats_lock);
- switch (*mp->b_rptr) {
- case PPPCTL_IERROR:
- #ifdef INCR_IERRORS
- INCR_IERRORS(ppa);
- #endif
- ppa->stats.ppp_ierrors++;
- break;
- case PPPCTL_OERROR:
- #ifdef INCR_OERRORS
- INCR_OERRORS(ppa);
- #endif
- ppa->stats.ppp_oerrors++;
- break;
- }
- MT_EXIT(&ppa->stats_lock);
- freemsg(mp);
- break;
- case M_IOCACK:
- case M_IOCNAK:
-
- iop = (struct iocblk *) mp->b_rptr;
- for (us = ppa; us != 0; us = us->next)
- if (us->ioc_id == iop->ioc_id)
- break;
- if (us == 0)
- freemsg(mp);
- else
- putnext(us->q, mp);
- break;
- case M_HANGUP:
-
- freemsg(mp);
- mp = allocb(1, BPRI_HI);
- if (mp == 0) {
- DPRINT1("ppp/%d: couldn't allocate eof message!\n", ppa->mn);
- break;
- }
- putnext(ppa->q, mp);
- break;
- default:
- if (mp->b_datap->db_type == M_DATA) {
- len = msgdsize(mp);
- if (mp->b_wptr - mp->b_rptr < PPP_HDRLEN) {
- PULLUP(mp, PPP_HDRLEN);
- if (mp == 0) {
- DPRINT1("ppp_urput: msgpullup failed (len=%d)\n", len);
- break;
- }
- }
- MT_ENTER(&ppa->stats_lock);
- ppa->stats.ppp_ipackets++;
- ppa->stats.ppp_ibytes += len;
- #ifdef INCR_IPACKETS
- INCR_IPACKETS(ppa);
- #endif
- MT_EXIT(&ppa->stats_lock);
- proto = PPP_PROTOCOL(mp->b_rptr);
- #if defined(SOL2)
-
- promisc_sendup(ppa, mp, proto, 1);
- #endif
- if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
-
- if (!pass_packet(us, mp, 0))
- break;
- if (!us->rblocked && !canput(us->q))
- us->rblocked = 1;
- if (!us->rblocked)
- putq(us->q, mp);
- else
- putq(q, mp);
- break;
- }
- }
-
- if (queclass(mp) == QPCTL || canputnext(ppa->q))
- putnext(ppa->q, mp);
- else
- putq(q, mp);
- break;
- }
- return 0;
- }
- static int
- pppursrv(q)
- queue_t *q;
- {
- upperstr_t *us, *as;
- mblk_t *mp, *hdr;
- #ifndef NO_DLPI
- dl_unitdata_ind_t *ud;
- #endif
- int proto;
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("pppursrv: q_ptr = 0!\n");
- return 0;
- }
- if (us->flags & US_CONTROL) {
-
- if (us->lowerq == 0) {
- as = us;
- do {
- if (as->flags & US_BLOCKED)
- qenable(WR(as->q));
- as = as->next;
- } while (as != 0);
- }
-
- while ((mp = getq(q)) != 0) {
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (proto < 0x8000 && (as = find_dest(us, proto)) != 0) {
- if (!canput(as->q))
- break;
- putq(as->q, mp);
- } else {
- if (!canputnext(q))
- break;
- putnext(q, mp);
- }
- }
- if (mp) {
- putbq(q, mp);
- } else {
-
- for (as = us->next; as != 0; as = as->next)
- as->rblocked = 0;
- }
-
- if (us->lowerq != 0)
- qenable(RD(us->lowerq));
-
- } else {
-
- while ((mp = getq(q)) != 0) {
- if (!canputnext(q)) {
- putbq(q, mp);
- break;
- }
- #ifndef NO_DLPI
- proto = PPP_PROTOCOL(mp->b_rptr);
- mp->b_rptr += PPP_HDRLEN;
- hdr = allocb(sizeof(dl_unitdata_ind_t) + 2 * sizeof(uint),
- BPRI_MED);
- if (hdr == 0) {
-
- freemsg(mp);
- continue;
- }
- hdr->b_datap->db_type = M_PROTO;
- ud = (dl_unitdata_ind_t *) hdr->b_wptr;
- hdr->b_wptr += sizeof(dl_unitdata_ind_t) + 2 * sizeof(uint);
- hdr->b_cont = mp;
- ud->dl_primitive = DL_UNITDATA_IND;
- ud->dl_dest_addr_length = sizeof(uint);
- ud->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
- ud->dl_src_addr_length = sizeof(uint);
- ud->dl_src_addr_offset = ud->dl_dest_addr_offset + sizeof(uint);
- #if DL_CURRENT_VERSION >= 2
- ud->dl_group_address = 0;
- #endif
-
- ((uint *)(ud + 1))[0] = us->req_sap;
- ((uint *)(ud + 1))[1] = us->req_sap;
- putnext(q, hdr);
- #else
- putnext(q, mp);
- #endif
- }
-
- if (us->ppa)
- qenable(us->ppa->q);
- }
- return 0;
- }
- static upperstr_t *
- find_dest(ppa, proto)
- upperstr_t *ppa;
- int proto;
- {
- upperstr_t *us;
- for (us = ppa->next; us != 0; us = us->next)
- if (proto == us->sap)
- break;
- return us;
- }
- #if defined (SOL2)
- static upperstr_t *
- find_promisc(us, proto)
- upperstr_t *us;
- int proto;
- {
- if ((proto != PPP_IP) && (proto != PPP_IPV6))
- return (upperstr_t *)0;
- for ( ; us; us = us->next) {
- if ((us->flags & US_PROMISC) && (us->state == DL_IDLE))
- return us;
- }
- return (upperstr_t *)0;
- }
- static mblk_t *
- prepend_ether(us, mp, proto)
- upperstr_t *us;
- mblk_t *mp;
- int proto;
- {
- mblk_t *eh;
- int type;
- if ((eh = allocb(sizeof(struct ether_header), BPRI_HI)) == 0) {
- freemsg(mp);
- return (mblk_t *)0;
- }
- if (proto == PPP_IP)
- type = ETHERTYPE_IP;
- else if (proto == PPP_IPV6)
- type = ETHERTYPE_IPV6;
- else
- type = proto;
- eh->b_wptr += sizeof(struct ether_header);
- bzero((caddr_t)eh->b_rptr, sizeof(struct ether_header));
- ((struct ether_header *)eh->b_rptr)->ether_type = htons((short)type);
- eh->b_cont = mp;
- return (eh);
- }
- static mblk_t *
- prepend_udind(us, mp, proto)
- upperstr_t *us;
- mblk_t *mp;
- int proto;
- {
- dl_unitdata_ind_t *dlu;
- mblk_t *dh;
- size_t size;
- size = sizeof(dl_unitdata_ind_t);
- if ((dh = allocb(size, BPRI_MED)) == 0) {
- freemsg(mp);
- return (mblk_t *)0;
- }
- dh->b_datap->db_type = M_PROTO;
- dh->b_wptr = dh->b_datap->db_lim;
- dh->b_rptr = dh->b_wptr - size;
- dlu = (dl_unitdata_ind_t *)dh->b_rptr;
- dlu->dl_primitive = DL_UNITDATA_IND;
- dlu->dl_dest_addr_length = 0;
- dlu->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
- dlu->dl_src_addr_length = 0;
- dlu->dl_src_addr_offset = sizeof(dl_unitdata_ind_t);
- dlu->dl_group_address = 0;
- dh->b_cont = mp;
- return (dh);
- }
- static void
- promisc_sendup(ppa, mp, proto, skip)
- upperstr_t *ppa;
- mblk_t *mp;
- int proto, skip;
- {
- mblk_t *dup_mp, *dup_dup_mp;
- upperstr_t *prus, *nprus;
- if ((prus = find_promisc(ppa, proto)) != 0) {
- if (dup_mp = dupmsg(mp)) {
- if (skip)
- dup_mp->b_rptr += PPP_HDRLEN;
- for ( ; nprus = find_promisc(prus->next, proto);
- prus = nprus) {
- if (dup_dup_mp = dupmsg(dup_mp)) {
- if (canputnext(prus->q)) {
- if (prus->flags & US_RAWDATA) {
- dup_dup_mp = prepend_ether(prus, dup_dup_mp, proto);
- putnext(prus->q, dup_dup_mp);
- } else {
- dup_dup_mp = prepend_udind(prus, dup_dup_mp, proto);
- putnext(prus->q, dup_dup_mp);
- }
- } else {
- DPRINT("ppp_urput: data to promisc q dropped\n");
- freemsg(dup_dup_mp);
- }
- }
- }
- if (canputnext(prus->q)) {
- if (prus->flags & US_RAWDATA) {
- dup_mp = prepend_ether(prus, dup_mp, proto);
- putnext(prus->q, dup_mp);
- } else {
- dup_mp = prepend_udind(prus, dup_mp, proto);
- putnext(prus->q, dup_mp);
- }
- } else {
- DPRINT("ppp_urput: data to promisc q dropped\n");
- freemsg(dup_mp);
- }
- }
- }
- }
- #endif
- static int
- ppplrput(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- queue_t *uq;
- struct iocblk *iop;
- switch (mp->b_datap->db_type) {
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- iop->ioc_error = EINVAL;
- mp->b_datap->db_type = M_IOCNAK;
- qreply(q, mp);
- return 0;
- case M_FLUSH:
- if (*mp->b_rptr & FLUSHR)
- flushq(q, FLUSHDATA);
- if (*mp->b_rptr & FLUSHW) {
- *mp->b_rptr &= ~FLUSHR;
- qreply(q, mp);
- } else
- freemsg(mp);
- return 0;
- }
-
- if (!TRYLOCK_LOWER_R) {
- putq(q, mp);
- return 0;
- }
-
- uq = (queue_t *) q->q_ptr;
- if (uq == 0) {
- UNLOCK_LOWER;
- DPRINT1("ppplrput: q = %x, uq = 0??\n", q);
- freemsg(mp);
- return 0;
- }
-
- if (queclass(mp) == QPCTL || (qsize(q) == 0 && canput(uq)))
- put(uq, mp);
- else
- putq(q, mp);
- UNLOCK_LOWER;
- return 0;
- }
- static int
- ppplrsrv(q)
- queue_t *q;
- {
- mblk_t *mp;
- queue_t *uq;
-
- LOCK_LOWER_R;
- uq = (queue_t *) q->q_ptr;
- if (uq == 0) {
- UNLOCK_LOWER;
- flushq(q, FLUSHALL);
- DPRINT1("ppplrsrv: q = %x, uq = 0??\n", q);
- return 0;
- }
- while ((mp = getq(q)) != 0) {
- if (queclass(mp) == QPCTL || canput(uq))
- put(uq, mp);
- else {
- putbq(q, mp);
- break;
- }
- }
- UNLOCK_LOWER;
- return 0;
- }
- static int
- putctl2(q, type, code, val)
- queue_t *q;
- int type, code, val;
- {
- mblk_t *mp;
- mp = allocb(2, BPRI_HI);
- if (mp == 0)
- return 0;
- mp->b_datap->db_type = type;
- mp->b_wptr[0] = code;
- mp->b_wptr[1] = val;
- mp->b_wptr += 2;
- putnext(q, mp);
- return 1;
- }
- static int
- putctl4(q, type, code, val)
- queue_t *q;
- int type, code, val;
- {
- mblk_t *mp;
- mp = allocb(4, BPRI_HI);
- if (mp == 0)
- return 0;
- mp->b_datap->db_type = type;
- mp->b_wptr[0] = code;
- ((short *)mp->b_wptr)[1] = val;
- mp->b_wptr += 4;
- putnext(q, mp);
- return 1;
- }
- static void
- debug_dump(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- upperstr_t *us;
- queue_t *uq, *lq;
- DPRINT("ppp upper streams:\n");
- for (us = minor_devs; us != 0; us = us->nextmn) {
- uq = us->q;
- DPRINT3(" %d: q=%x rlev=%d",
- us->mn, uq, (uq? qsize(uq): 0));
- DPRINT3(" wlev=%d flags=0x%b", (uq? qsize(WR(uq)): 0),
- us->flags, "\020\1priv\2control\3blocked\4last");
- DPRINT3(" state=%x sap=%x req_sap=%x", us->state, us->sap,
- us->req_sap);
- if (us->ppa == 0)
- DPRINT(" ppa=?\n");
- else
- DPRINT1(" ppa=%d\n", us->ppa->ppa_id);
- if (us->flags & US_CONTROL) {
- lq = us->lowerq;
- DPRINT3(" control for %d lq=%x rlev=%d",
- us->ppa_id, lq, (lq? qsize(RD(lq)): 0));
- DPRINT3(" wlev=%d mru=%d mtu=%d\n",
- (lq? qsize(lq): 0), us->mru, us->mtu);
- }
- }
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- }
- #ifdef FILTER_PACKETS
- #include <netinet/in_systm.h>
- #include <netinet/ip.h>
- #include <netinet/udp.h>
- #include <netinet/tcp.h>
- #define MAX_IPHDR 128
- static struct pktfilt_tab {
- int proto;
- u_short port;
- u_short ok_if_link_up;
- } pktfilt_tab[] = {
- { IPPROTO_UDP, 520, 1 },
- { IPPROTO_UDP, 123, 1 },
- { -1, 0, 0 }
- };
- static int
- ip_hard_filter(us, mp, outbound)
- upperstr_t *us;
- mblk_t *mp;
- int outbound;
- {
- struct ip *ip;
- struct pktfilt_tab *pft;
- mblk_t *temp_mp;
- int proto;
- int len, hlen;
-
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: filter, proto=0x%x, out=%d\n", us->mn, proto, outbound);
- switch (proto)
- {
- case PPP_IP:
- if ((mp->b_wptr - mp->b_rptr) == PPP_HDRLEN && mp->b_cont != 0) {
- temp_mp = mp->b_cont;
- len = msgdsize(temp_mp);
- hlen = (len < MAX_IPHDR) ? len : MAX_IPHDR;
- PULLUP(temp_mp, hlen);
- if (temp_mp == 0) {
- DPRINT2("ppp/%d: filter, pullup next failed, len=%d\n",
- us->mn, hlen);
- mp->b_cont = 0;
- freemsg(mp);
- return 0;
- }
- ip = (struct ip *)mp->b_cont->b_rptr;
- }
- else {
- len = msgdsize(mp);
- hlen = (len < (PPP_HDRLEN+MAX_IPHDR)) ? len : (PPP_HDRLEN+MAX_IPHDR);
- PULLUP(mp, hlen);
- if (mp == 0) {
- DPRINT2("ppp/%d: filter, pullup failed, len=%d\n",
- us->mn, hlen);
- return 0;
- }
- ip = (struct ip *)(mp->b_rptr + PPP_HDRLEN);
- }
-
- for (pft=pktfilt_tab; pft->proto != -1; pft++) {
- if (ip->ip_p == pft->proto) {
- switch(pft->proto) {
- case IPPROTO_UDP:
- if (((struct udphdr *) &((int *)ip)[ip->ip_hl])->uh_dport
- == htons(pft->port)) goto endfor;
- break;
- case IPPROTO_TCP:
- if (((struct tcphdr *) &((int *)ip)[ip->ip_hl])->th_dport
- == htons(pft->port)) goto endfor;
- break;
- }
- }
- }
- endfor:
- if (pft->proto != -1) {
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: found IP pkt, proto=0x%x (%d)\n",
- us->mn, pft->proto, pft->port);
-
-
- return pft->ok_if_link_up? -1: 0;
- }
- break;
- }
- return 1;
- }
- #endif
|