📄 if_spppsubr.c
字号:
struct ppp_header *h; struct lcp_header *lh; struct mbuf *m; struct ifnet *ifp = &sp->pp_if; if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; MGETHDR (m, M_DONTWAIT, MT_DATA); if (! m) return; m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; m->m_pkthdr.rcvif = 0; h = mtod (m, struct ppp_header*); h->address = PPP_ALLSTATIONS; /* broadcast address */ h->control = PPP_UI; /* Unnumbered Info */ h->protocol = htons (proto); /* Link Control Protocol */ lh = (struct lcp_header*) (h + 1); lh->type = type; lh->ident = ident; lh->len = htons (LCP_HEADER_LEN + len); if (len) bcopy (data, lh+1, len); if (ifp->if_flags & IFF_DEBUG) { printf ("%s%d: %s output <%s id=%xh len=%xh", ifp->if_name, ifp->if_unit, proto==PPP_LCP ? "lcp" : "ipcp", proto==PPP_LCP ? sppp_lcp_type_name (lh->type) : sppp_ipcp_type_name (lh->type), lh->ident, ntohs (lh->len)); if (len) sppp_print_bytes ((u_char*) (lh+1), len); printf (">\n"); } if (IF_QFULL (&sp->pp_fastq)) { IF_DROP (&ifp->if_snd); m_freem (m); } else IF_ENQUEUE (&sp->pp_fastq, m); if (! (ifp->if_flags & IFF_OACTIVE)) (*ifp->if_start) (ifp); ifp->if_obytes += m->m_pkthdr.len + 3;}/* * Send Cisco keepalive packet. */void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2){ struct ppp_header *h; struct cisco_packet *ch; struct mbuf *m; struct ifnet *ifp = &sp->pp_if; u_long t = (time.tv_sec - boottime.tv_sec) * 1000; MGETHDR (m, M_DONTWAIT, MT_DATA); if (! m) return; m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; m->m_pkthdr.rcvif = 0; h = mtod (m, struct ppp_header*); h->address = CISCO_MULTICAST; h->control = 0; h->protocol = htons (CISCO_KEEPALIVE); ch = (struct cisco_packet*) (h + 1); ch->type = htonl (type); ch->par1 = htonl (par1); ch->par2 = htonl (par2); ch->rel = -1; ch->time0 = htons ((u_short) (t >> 16)); ch->time1 = htons ((u_short) t); if (ifp->if_flags & IFF_DEBUG) printf ("%s%d: cisco output: <%lxh %lxh %lxh %xh %xh-%xh>\n", ifp->if_name, ifp->if_unit, ntohl (ch->type), ch->par1, ch->par2, ch->rel, ch->time0, ch->time1); if (IF_QFULL (&sp->pp_fastq)) { IF_DROP (&ifp->if_snd); m_freem (m); } else IF_ENQUEUE (&sp->pp_fastq, m); if (! (ifp->if_flags & IFF_OACTIVE)) (*ifp->if_start) (ifp); ifp->if_obytes += m->m_pkthdr.len + 3;}/* * Process an ioctl request. Called on low priority level. */int sppp_ioctl (struct ifnet *ifp, int cmd, void *data){ struct ifreq *ifr = (struct ifreq*) data; struct sppp *sp = (struct sppp*) ifp; int s, going_up, going_down; switch (cmd) { default: return (EINVAL); case SIOCAIFADDR: case SIOCSIFDSTADDR: break; case SIOCSIFADDR: ifp->if_flags |= IFF_UP; /* fall through... */ case SIOCSIFFLAGS: s = splimp (); going_up = (ifp->if_flags & IFF_UP) && ! (ifp->if_flags & IFF_RUNNING); going_down = ! (ifp->if_flags & IFF_UP) && (ifp->if_flags & IFF_RUNNING); if (going_up || going_down) { /* Shut down the PPP link. */ ifp->if_flags &= ~IFF_RUNNING; sp->lcp.state = LCP_STATE_CLOSED; sp->ipcp.state = IPCP_STATE_CLOSED; UNTIMO (sp); } if (going_up) { /* Interface is starting -- initiate negotiation. */ ifp->if_flags |= IFF_RUNNING; if (!(sp->pp_flags & PP_CISCO)) sppp_lcp_open (sp); } splx (s); break;#ifdef SIOCSIFMTU#ifndef ifr_mtu#define ifr_mtu ifr_metric#endif case SIOCSIFMTU: if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > PP_MTU) return (EINVAL); ifp->if_mtu = ifr->ifr_mtu; break;#endif#ifdef SLIOCSETMTU case SLIOCSETMTU: if (*(short*)data < 128 || *(short*)data > PP_MTU) return (EINVAL); ifp->if_mtu = *(short*)data; break;#endif#ifdef SIOCGIFMTU case SIOCGIFMTU: ifr->ifr_mtu = ifp->if_mtu; break;#endif#ifdef SLIOCGETMTU case SLIOCGETMTU: *(short*)data = ifp->if_mtu; break;#endif#ifdef MULTICAST case SIOCADDMULTI: case SIOCDELMULTI: break;#endif } return (0);}/* * Analyze the LCP Configure-Request options list * for the presence of unknown options. * If the request contains unknown options, build and * send Configure-reject packet, containing only unknown options. */int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h, int len, u_long *magic){ u_char *buf, *r, *p; int rlen; len -= 4; buf = r = malloc (len, M_TEMP, M_NOWAIT); if (! buf) return (0); p = (void*) (h+1); for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { switch (*p) { case LCP_OPT_MAGIC: /* Magic number -- extract. */ if (len >= 6 && p[1] == 6) { *magic = (u_long)p[2] << 24 | (u_long)p[3] << 16 | p[4] << 8 | p[5]; continue; } break; case LCP_OPT_ASYNC_MAP: /* Async control character map -- check to be zero. */ if (len >= 6 && p[1] == 6 && ! p[2] && ! p[3] && ! p[4] && ! p[5]) continue; break; case LCP_OPT_MRU: /* Maximum receive unit -- always OK. */ continue; default: /* Others not supported. */ break; } /* Add the option to rejected list. */ bcopy (p, r, p[1]); r += p[1]; rlen += p[1]; } if (rlen) sppp_cp_send (sp, PPP_LCP, LCP_CONF_REJ, h->ident, rlen, buf); free (buf, M_TEMP); return (rlen == 0);}void sppp_ipcp_input (struct sppp *sp, struct mbuf *m){ struct lcp_header *h; struct ifnet *ifp = &sp->pp_if; int len = m->m_pkthdr.len; if (len < 4) { /* if (ifp->if_flags & IFF_DEBUG) */ printf ("%s%d: invalid ipcp packet length: %d bytes\n", ifp->if_name, ifp->if_unit, len); return; } h = mtod (m, struct lcp_header*); if (ifp->if_flags & IFF_DEBUG) { printf ("%s%d: ipcp input: %d bytes <%s id=%xh len=%xh", ifp->if_name, ifp->if_unit, len, sppp_ipcp_type_name (h->type), h->ident, ntohs (h->len)); if (len > 4) sppp_print_bytes ((u_char*) (h+1), len-4); printf (">\n"); } if (len > ntohs (h->len)) len = ntohs (h->len); switch (h->type) { default: /* Unknown packet type -- send Code-Reject packet. */ sppp_cp_send (sp, PPP_IPCP, IPCP_CODE_REJ, ++sp->pp_seq, len, h); break; case IPCP_CONF_REQ: if (len < 4) { if (ifp->if_flags & IFF_DEBUG) printf ("%s%d: invalid ipcp configure request packet length: %d bytes\n", ifp->if_name, ifp->if_unit, len); return; } if (len > 4) { sppp_cp_send (sp, PPP_IPCP, LCP_CONF_REJ, h->ident, len-4, h+1); switch (sp->ipcp.state) { case IPCP_STATE_OPENED: /* Initiate renegotiation. */ sppp_ipcp_open (sp); /* fall through... */ case IPCP_STATE_ACK_SENT: /* Go to closed state. */ sp->ipcp.state = IPCP_STATE_CLOSED; } } else { /* Send Configure-Ack packet. */ sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_ACK, h->ident, 0, 0); /* Change the state. */ if (sp->ipcp.state == IPCP_STATE_ACK_RCVD) sp->ipcp.state = IPCP_STATE_OPENED; else sp->ipcp.state = IPCP_STATE_ACK_SENT; } break; case IPCP_CONF_ACK: if (h->ident != sp->ipcp.confid) break; UNTIMO (sp); switch (sp->ipcp.state) { case IPCP_STATE_CLOSED: sp->ipcp.state = IPCP_STATE_ACK_RCVD; TIMO (sp, 5); break; case IPCP_STATE_ACK_SENT: sp->ipcp.state = IPCP_STATE_OPENED; break; } break; case IPCP_CONF_NAK: case IPCP_CONF_REJ: if (h->ident != sp->ipcp.confid) break; UNTIMO (sp); /* Initiate renegotiation. */ sppp_ipcp_open (sp); if (sp->ipcp.state != IPCP_STATE_ACK_SENT) /* Go to closed state. */ sp->ipcp.state = IPCP_STATE_CLOSED; break; case IPCP_TERM_REQ: /* Send Terminate-Ack packet. */ sppp_cp_send (sp, PPP_IPCP, IPCP_TERM_ACK, h->ident, 0, 0); /* Go to closed state. */ sp->ipcp.state = IPCP_STATE_CLOSED; /* Initiate renegotiation. */ sppp_ipcp_open (sp); break; case IPCP_TERM_ACK: /* Ignore for now. */ case IPCP_CODE_REJ: /* Ignore for now. */ break; }}void sppp_lcp_open (struct sppp *sp){ char opt[6]; if (! sp->lcp.magic) sp->lcp.magic = time.tv_sec + time.tv_usec; opt[0] = LCP_OPT_MAGIC; opt[1] = sizeof (opt); opt[2] = sp->lcp.magic >> 24; opt[3] = sp->lcp.magic >> 16; opt[4] = sp->lcp.magic >> 8; opt[5] = sp->lcp.magic; sp->lcp.confid = ++sp->pp_seq; sppp_cp_send (sp, PPP_LCP, LCP_CONF_REQ, sp->lcp.confid, sizeof (opt), &opt); TIMO (sp, 2);}void sppp_ipcp_open (struct sppp *sp){ sp->ipcp.confid = ++sp->pp_seq; sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_REQ, sp->ipcp.confid, 0, 0); TIMO (sp, 2);}/* * Process PPP control protocol timeouts. */void sppp_cp_timeout (void *arg){ struct sppp *sp = (struct sppp*) arg; int s = splimp (); sp->pp_flags &= ~PP_TIMO; if (! (sp->pp_if.if_flags & IFF_RUNNING) || (sp->pp_flags & PP_CISCO)) { splx (s); return; } switch (sp->lcp.state) { case LCP_STATE_CLOSED: /* No ACK for Configure-Request, retry. */ sppp_lcp_open (sp); break; case LCP_STATE_ACK_RCVD: /* ACK got, but no Configure-Request for peer, retry. */ sppp_lcp_open (sp); sp->lcp.state = LCP_STATE_CLOSED; break; case LCP_STATE_ACK_SENT: /* ACK sent but no ACK for Configure-Request, retry. */ sppp_lcp_open (sp); break; case LCP_STATE_OPENED: /* LCP is already OK, try IPCP. */ switch (sp->ipcp.state) { case IPCP_STATE_CLOSED: /* No ACK for Configure-Request, retry. */ sppp_ipcp_open (sp); break; case IPCP_STATE_ACK_RCVD: /* ACK got, but no Configure-Request for peer, retry. */ sppp_ipcp_open (sp); sp->ipcp.state = IPCP_STATE_CLOSED; break; case IPCP_STATE_ACK_SENT: /* ACK sent but no ACK for Configure-Request, retry. */ sppp_ipcp_open (sp); break; case IPCP_STATE_OPENED: /* IPCP is OK. */ break; } break; } splx (s);}char *sppp_lcp_type_name (u_char type){ static char buf [8]; switch (type) { case LCP_CONF_REQ: return ("conf-req"); case LCP_CONF_ACK: return ("conf-ack"); case LCP_CONF_NAK: return ("conf-nack"); case LCP_CONF_REJ: return ("conf-rej"); case LCP_TERM_REQ: return ("term-req"); case LCP_TERM_ACK: return ("term-ack"); case LCP_CODE_REJ: return ("code-rej"); case LCP_PROTO_REJ: return ("proto-rej"); case LCP_ECHO_REQ: return ("echo-req"); case LCP_ECHO_REPLY: return ("echo-reply"); case LCP_DISC_REQ: return ("discard-req"); } sprintf (buf, "%xh", type); return (buf);}char *sppp_ipcp_type_name (u_char type){ static char buf [8]; switch (type) { case IPCP_CONF_REQ: return ("conf-req"); case IPCP_CONF_ACK: return ("conf-ack"); case IPCP_CONF_NAK: return ("conf-nack"); case IPCP_CONF_REJ: return ("conf-rej"); case IPCP_TERM_REQ: return ("term-req"); case IPCP_TERM_ACK: return ("term-ack"); case IPCP_CODE_REJ: return ("code-rej"); } sprintf (buf, "%xh", type); return (buf);}void sppp_print_bytes (u_char *p, u_short len){ printf (" %x", *p++); while (--len > 0) printf ("-%x", *p++);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -