X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=modules%2Fppp.c;h=0ed435b9904404a888415698076fd640b14ea70f;hp=164f1c87cc64083877015771cd7ad31c0f7d04a6;hb=da44517ffef30eb2c170bb97cd6435f6d4e61a0e;hpb=ac19750e0fb64986870e9bd9bad52d5ae46e2551 diff --git a/modules/ppp.c b/modules/ppp.c index 164f1c8..0ed435b 100644 --- a/modules/ppp.c +++ b/modules/ppp.c @@ -24,7 +24,7 @@ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, * OR MODIFICATIONS. * - * $Id: ppp.c,v 1.17 1999/03/08 05:34:16 paulus Exp $ + * $Id: ppp.c,v 1.25 1999/10/08 01:10:12 masputra Exp $ */ /* @@ -54,6 +54,7 @@ #include #include #include +#include #else #include #include @@ -72,9 +73,10 @@ * interactive traffic, and are due to Marko Zec . */ #ifdef PRIOQ -#include #endif /* PRIOQ */ +#include /* leave this outside of PRIOQ for htons */ + #ifdef __STDC__ #define __P(x) x #else @@ -88,6 +90,18 @@ #define ETHERTYPE_IP 0x800 #endif +#if !defined(ETHERTYPE_IPV6) +#define ETHERTYPE_IPV6 0x86dd +#endif /* !defined(ETHERTYPE_IPV6) */ + +#if !defined(ETHERTYPE_ALLSAP) && defined(SOL2) +#define ETHERTYPE_ALLSAP 0 +#endif /* !defined(ETHERTYPE_ALLSAP) && defined(SOL2) */ + +#if !defined(PPP_ALLSAP) && defined(SOL2) +#define PPP_ALLSAP PPP_ALLSTATIONS +#endif /* !defined(PPP_ALLSAP) && defined(SOL2) */ + extern time_t time; #ifdef SOL2 @@ -193,6 +207,12 @@ typedef struct upperstr { #define US_DBGLOG 0x10 /* log various occurrences */ #define US_RBLOCKED 0x20 /* flow ctrl has blocked upper read stream */ +#if defined(SOL2) +#if DL_CURRENT_VERSION >= 2 +#define US_PROMISC 0x40 /* stream is promiscuous */ +#endif /* DL_CURRENT_VERSION >= 2 */ +#define US_RAWDATA 0x80 /* raw M_DATA, no DLPI header */ +#endif /* defined(SOL2) */ #ifdef PRIOQ static u_char max_band=0; @@ -252,10 +272,18 @@ 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 /* defined(SOL2) */ 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 /* FILTER_PACKETS */ #define PPP_ID 0xb1a6 static struct module_info ppp_info = { @@ -556,7 +584,7 @@ pppuwput(q, mp) queue_t *q; mblk_t *mp; { - upperstr_t *us, *usnext, *ppa, *os, *nps; + upperstr_t *us, *ppa, *nps; struct iocblk *iop; struct linkblk *lb; #ifdef LACHTCP @@ -567,10 +595,12 @@ pppuwput(q, mp) int error, n, sap; mblk_t *mq; struct ppp_idle *pip; - int len; #ifdef PRIOQ queue_t *tlq; #endif /* PRIOQ */ +#ifdef NO_DLPI + upperstr_t *os; +#endif us = (upperstr_t *) q->q_ptr; if (us == 0) { @@ -621,6 +651,12 @@ pppuwput(q, mp) 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: /* raw M_DATA mode */ + us->flags |= US_RAWDATA; + error = 0; + break; +#endif /* defined(SOL2) */ case I_LINK: if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0) break; @@ -809,7 +845,7 @@ pppuwput(q, mp) if (n == PPPDBG_DUMP + PPPDBG_DRIVER) { qwriter(q, NULL, debug_dump, PERIM_OUTER); iop->ioc_count = 0; - error = 0; + error = -1; } else if (n == PPPDBG_LOG + PPPDBG_DRIVER) { DPRINT1("ppp/%d: debug log enabled\n", us->mn); us->flags |= US_DBGLOG; @@ -833,9 +869,12 @@ pppuwput(q, mp) break; } sap = ((int *)mp->b_cont->b_rptr)[0]; - for (nps = us->next; nps != 0; nps = nps->next) + 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); @@ -1042,9 +1081,13 @@ dlpi_request(q, mp, us) int size = mp->b_wptr - mp->b_rptr; mblk_t *reply, *np; upperstr_t *ppa, *os; - int sap, *ip, len; + 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, @@ -1063,15 +1106,7 @@ dlpi_request(q, mp, us) info->dl_max_sdu = us->ppa? us->ppa->mtu: PPP_MAXMTU; info->dl_min_sdu = 1; info->dl_addr_length = sizeof(uint); -#if 0 -#ifdef DL_OTHER - info->dl_mac_type = DL_OTHER; -#else - info->dl_mac_type = DL_HDLC; /* a lie */ -#endif -#else info->dl_mac_type = DL_ETHER; /* a bigger lie */ -#endif info->dl_current_state = us->state; info->dl_service_mode = DL_CLDLS; info->dl_provider_style = DL_STYLE2; @@ -1098,7 +1133,7 @@ dlpi_request(q, mp, us) } us->ppa = ppa; qwriter(q, mp, attach_ppa, PERIM_OUTER); - break; + return; case DL_DETACH_REQ: if (size < sizeof(dl_detach_req_t)) @@ -1108,7 +1143,7 @@ dlpi_request(q, mp, us) break; } qwriter(q, mp, detach_ppa, PERIM_OUTER); - break; + return; case DL_BIND_REQ: if (size < sizeof(dl_bind_req_t)) @@ -1129,12 +1164,30 @@ dlpi_request(q, mp, us) except that we accept ETHERTYPE_IP in place of PPP_IP. */ 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) /* normal IFF_IPV4 */ + sap = PPP_IP; + else if (sap == ETHERTYPE_IPV6) /* when IFF_IPV6 is set */ + sap = PPP_IPV6; + else if (sap == ETHERTYPE_ALLSAP) /* snoop gives sap of 0 */ + 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 /* defined(SOL2) */ /* check that no other stream is bound to this sap already. */ for (os = us->ppa; os != 0; os = os->next) @@ -1194,6 +1247,16 @@ dlpi_request(q, mp, us) DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu); break; } + +#if defined(SOL2) + /* + * Should there be any promiscuous stream(s), send the data + * up for each promiscuous stream that we recognize. + */ + if (mp->b_cont) + promisc_sendup(ppa, mp->b_cont, us->sap, 0); +#endif /* defined(SOL2) */ + mp->b_band = 0; #ifdef PRIOQ /* Extract s_port & d_port from IP-packet, the code is a bit @@ -1281,14 +1344,55 @@ dlpi_request(q, mp, us) return; #if DL_CURRENT_VERSION >= 2 + case DL_PHYS_ADDR_REQ: + if (size < sizeof(dl_phys_addr_req_t)) + goto badprim; + + /* + * Don't check state because ifconfig sends this one down too + */ + + if ((reply = allocb(sizeof(dl_phys_addr_ack_t)+ETHERADDRL, + BPRI_HI)) == 0) + break; /* should do bufcall */ + 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: /* fall thru */ + case DL_PROMISCOFF_REQ: /* fall thru */ +#endif /* defined(SOL2) */ +#endif /* DL_CURRENT_VERSION >= 2 */ + +#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_PROMISCON_REQ: - case DL_PROMISCOFF_REQ: - case DL_PHYS_ADDR_REQ: - case DL_SET_PHYS_ADDR_REQ: case DL_XID_REQ: case DL_TEST_REQ: case DL_REPLY_UPDATE_REQ: @@ -1423,7 +1527,6 @@ send_data(mp, us) mblk_t *mp; upperstr_t *us; { - queue_t *q; upperstr_t *ppa; if ((us->flags & US_BLOCKED) || us->npmode == NPMODE_QUEUE) @@ -1435,7 +1538,7 @@ send_data(mp, us) freemsg(mp); return 1; } - if ((q = ppa->lowerq) == 0) { + if (ppa->lowerq == 0) { /* try to send it up the control stream */ if (bcanputnext(ppa->q, mp->b_band)) { /* @@ -1699,9 +1802,7 @@ pppurput(q, mp) mblk_t *mp; { upperstr_t *ppa, *us; - queue_t *uq; int proto, len; - mblk_t *np; struct iocblk *iop; ppa = (upperstr_t *) q->q_ptr; @@ -1782,6 +1883,15 @@ pppurput(q, mp) MT_EXIT(&ppa->stats_lock); proto = PPP_PROTOCOL(mp->b_rptr); + +#if defined(SOL2) + /* + * Should there be any promiscuous stream(s), send the data + * up for each promiscuous stream that we recognize. + */ + promisc_sendup(ppa, mp, proto, 1); +#endif /* defined(SOL2) */ + if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) { /* * A data packet for some network protocol. @@ -1955,6 +2065,148 @@ find_dest(ppa, proto) return us; } +#if defined (SOL2) +/* + * Test upstream promiscuous conditions. As of now, only pass IPv4 and + * Ipv6 packets upstream (let PPP packets be decoded elsewhere). + */ +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; +} + +/* + * Prepend an empty Ethernet header to msg for snoop, et al. + */ +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; /* What else? Let decoder decide */ + + 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); +} + +/* + * Prepend DL_UNITDATA_IND mblk to msg + */ +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); +} + +/* + * For any recognized promiscuous streams, send data upstream + */ +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 /* defined(SOL2) */ + /* * We simply put the message on to the associated upper control stream * (either here or in ppplrsrv). That way we enter the perimeters @@ -1967,6 +2219,25 @@ ppplrput(q, mp) 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 we can't get the lower lock straight away, queue this one @@ -2073,8 +2344,8 @@ putctl4(q, type, code, val) static void debug_dump(q, mp) - queue_t *q; /* not used */ - mblk_t *mp; /* not used either */ + queue_t *q; + mblk_t *mp; { upperstr_t *us; queue_t *uq, *lq; @@ -2100,6 +2371,8 @@ debug_dump(q, mp) (lq? qsize(lq): 0), us->mru, us->mtu); } } + mp->b_datap->db_type = M_IOCACK; + qreply(q, mp); } #ifdef FILTER_PACKETS