?? netipcp.c
字號(hào):
tl = ntohl(wo->ouraddr);
PUTLONG(tl, p);
}
} else {
go->ouraddr = ciaddr2; /* accept peer's idea */
}
}
ho->neg_addr = 1;
ho->old_addrs = 1;
ho->hisaddr = ciaddr1;
ho->ouraddr = ciaddr2;
break;
#endif
case CI_ADDR:
if (!ao->neg_addr) {
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR not allowed"));
orc = CONFREJ; /* Reject CI */
break;
} else if (cilen != CILEN_ADDR) { /* Check CI length */
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR bad len"));
orc = CONFREJ; /* Reject CI */
break;
}
/*
* If he has no address, or if we both have his address but
* disagree about it, then NAK it with our idea.
* In particular, if we don't know his address, but he does,
* then accept it.
*/
GETLONG(tl, p); /* Parse source address (his) */
ciaddr1 = htonl(tl);
if (ciaddr1 != wo->hisaddr
&& (ciaddr1 == 0 || !wo->accept_remote)) {
orc = CONFNAK;
if (!reject_if_disagree) {
DECPTR(sizeof(u_int32_t), p);
tl = ntohl(wo->hisaddr);
PUTLONG(tl, p);
}
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Nak ADDR %s", ip_ntoa(ciaddr1)));
} else if (ciaddr1 == 0 && wo->hisaddr == 0) {
/*
* Don't ACK an address of 0.0.0.0 - reject it instead.
*/
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR %s", ip_ntoa(ciaddr1)));
orc = CONFREJ;
wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
break;
}
ho->neg_addr = 1;
ho->hisaddr = ciaddr1;
IPCPDEBUG((LOG_INFO, "ipcp_reqci: ADDR %s", ip_ntoa(ciaddr1)));
break;
case CI_MS_DNS1:
case CI_MS_DNS2:
/* Microsoft primary or secondary DNS request */
d = citype == CI_MS_DNS2;
/* If we do not have a DNS address then we cannot send it */
if (ao->dnsaddr[d] == 0 ||
cilen != CILEN_ADDR) { /* Check CI length */
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting DNS%d Request ", d+1));
orc = CONFREJ; /* Reject CI */
break;
}
GETLONG(tl, p);
if (htonl(tl) != ao->dnsaddr[d]) {
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking DNS%d Request %d",
d+1, ip_ntoa(tl)));
DECPTR(sizeof(u_int32_t), p);
tl = ntohl(ao->dnsaddr[d]);
PUTLONG(tl, p);
orc = CONFNAK;
}
IPCPDEBUG((LOG_INFO, "ipcp_reqci: received DNS%d Request ", d+1));
break;
case CI_MS_WINS1:
case CI_MS_WINS2:
/* Microsoft primary or secondary WINS request */
d = citype == CI_MS_WINS2;
IPCPDEBUG((LOG_INFO, "ipcp_reqci: received WINS%d Request ", d+1));
/* If we do not have a DNS address then we cannot send it */
if (ao->winsaddr[d] == 0 ||
cilen != CILEN_ADDR) { /* Check CI length */
orc = CONFREJ; /* Reject CI */
break;
}
GETLONG(tl, p);
if (htonl(tl) != ao->winsaddr[d]) {
DECPTR(sizeof(u_int32_t), p);
tl = ntohl(ao->winsaddr[d]);
PUTLONG(tl, p);
orc = CONFNAK;
}
break;
case CI_COMPRESSTYPE:
if (!ao->neg_vj) {
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE not allowed"));
orc = CONFREJ;
break;
} else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE len=%d", cilen));
orc = CONFREJ;
break;
}
GETSHORT(cishort, p);
if (!(cishort == IPCP_VJ_COMP ||
(cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE %d", cishort));
orc = CONFREJ;
break;
}
ho->neg_vj = 1;
ho->vj_protocol = cishort;
if (cilen == CILEN_VJ) {
GETCHAR(maxslotindex, p);
if (maxslotindex > ao->maxslotindex) {
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ max slot %d", maxslotindex));
orc = CONFNAK;
if (!reject_if_disagree){
DECPTR(1, p);
PUTCHAR(ao->maxslotindex, p);
}
}
GETCHAR(cflag, p);
if (cflag && !ao->cflag) {
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ cflag %d", cflag));
orc = CONFNAK;
if (!reject_if_disagree){
DECPTR(1, p);
PUTCHAR(wo->cflag, p);
}
}
ho->maxslotindex = maxslotindex;
ho->cflag = cflag;
} else {
ho->old_vj = 1;
ho->maxslotindex = MAX_SLOTS - 1;
ho->cflag = 1;
}
IPCPDEBUG((LOG_INFO,
"ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d",
ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag));
break;
default:
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting unknown CI type %d", citype));
orc = CONFREJ;
break;
}
endswitch:
if (orc == CONFACK && /* Good CI */
rc != CONFACK) /* but prior CI wasnt? */
continue; /* Don't send this one */
if (orc == CONFNAK) { /* Nak this CI? */
if (reject_if_disagree) { /* Getting fed up with sending NAKs? */
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting too many naks"));
orc = CONFREJ; /* Get tough if so */
} else {
if (rc == CONFREJ) /* Rejecting prior CI? */
continue; /* Don't send this one */
if (rc == CONFACK) { /* Ack'd all prior CIs? */
rc = CONFNAK; /* Not anymore... */
ucp = inp; /* Backup */
}
}
}
if (orc == CONFREJ && /* Reject this CI */
rc != CONFREJ) { /* but no prior ones? */
rc = CONFREJ;
ucp = inp; /* Backup */
}
/* Need to move CI? */
if (ucp != cip)
BCOPY(cip, ucp, cilen); /* Move it */
/* Update output pointer */
INCPTR(cilen, ucp);
}
/*
* If we aren't rejecting this packet, and we want to negotiate
* their address, and they didn't send their address, then we
* send a NAK with a CI_ADDR option appended. We assume the
* input buffer is long enough that we can append the extra
* option safely.
*/
if (rc != CONFREJ && !ho->neg_addr &&
wo->req_addr && !reject_if_disagree) {
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Requesting peer address"));
if (rc == CONFACK) {
rc = CONFNAK;
ucp = inp; /* reset pointer */
wo->req_addr = 0; /* don't ask again */
}
PUTCHAR(CI_ADDR, ucp);
PUTCHAR(CILEN_ADDR, ucp);
tl = ntohl(wo->hisaddr);
PUTLONG(tl, ucp);
}
*len = (int)(ucp - inp); /* Compute output length */
IPCPDEBUG((LOG_INFO, "ipcp_reqci: returning Configure-%s", CODENAME(rc)));
return (rc); /* Return final code */
}
/*
* ip_check_options - check that any IP-related options are OK,
* and assign appropriate defaults.
*/
static void ip_check_options(void)
{
ipcp_options *wo = &ipcp_wantoptions[0];
/*
* Load our default IP address but allow the remote host to give us
* a new address.
*/
if (wo->ouraddr == 0 && !disable_defaultip) {
wo->accept_local = 1; /* don't insist on this default value */
wo->ouraddr = htonl(localHost);
}
}
/*
* ipcp_up - IPCP has come UP.
*
* Configure the IP network interface appropriately and bring it up.
*/
static void ipcp_up(fsm *f)
{
u_int32_t mask;
ipcp_options *ho = &ipcp_hisoptions[f->unit];
ipcp_options *go = &ipcp_gotoptions[f->unit];
ipcp_options *wo = &ipcp_wantoptions[f->unit];
np_up(f->unit, PPP_IP);
IPCPDEBUG((LOG_INFO, "ipcp: up"));
/*
* We must have a non-zero IP address for both ends of the link.
*/
if (!ho->neg_addr)
ho->hisaddr = wo->hisaddr;
if (ho->hisaddr == 0) {
trace(LOG_ERR, "Could not determine remote IP address");
ipcp_close(f->unit, "Could not determine remote IP address");
return;
}
if (go->ouraddr == 0) {
trace(LOG_ERR, "Could not determine local IP address");
ipcp_close(f->unit, "Could not determine local IP address");
return;
}
/*
* Check that the peer is allowed to use the IP address it wants.
*/
if (!auth_ip_addr(f->unit, ho->hisaddr)) {
trace(LOG_ERR, "Peer is not authorized to use remote address %s",
ip_ntoa(ho->hisaddr));
ipcp_close(f->unit, "Unauthorized remote IP address");
return;
}
/* set tcp compression */
sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
/*
* Set IP addresses and (if specified) netmask.
*/
mask = GetMask(go->ouraddr);
#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
ipcp_close(f->unit, "Interface configuration failed");
return;
}
#endif
/* bring the interface up for IP */
if (!sifup(f->unit)) {
IPCPDEBUG((LOG_WARNING, "sifup failed"));
ipcp_close(f->unit, "Interface configuration failed");
return;
}
#if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
ipcp_close(f->unit, "Interface configuration failed");
return;
}
#endif
sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
/* assign a default route through the interface if required */
if (ipcp_wantoptions[f->unit].default_route)
if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
default_route_set[f->unit] = 1;
trace(LOG_NOTICE, "local IP address %s", ip_ntoa(go->ouraddr));
trace(LOG_NOTICE, "remote IP address %s", ip_ntoa(ho->hisaddr));
}
/*
* ipcp_down - IPCP has gone DOWN.
*
* Take the IP network interface down, clear its addresses
* and delete routes through it.
*/
static void ipcp_down(fsm *f)
{
IPCPDEBUG((LOG_INFO, "ipcp: down"));
np_down(f->unit, PPP_IP);
sifvjcomp(f->unit, 0, 0, 0);
sifdown(f->unit);
ipcp_clear_addrs(f->unit);
}
/*
* ipcp_clear_addrs() - clear the interface addresses, routes, etc.
*/
static void ipcp_clear_addrs(int unit)
{
u_int32_t ouraddr, hisaddr;
ouraddr = ipcp_gotoptions[unit].ouraddr;
hisaddr = ipcp_hisoptions[unit].hisaddr;
if (default_route_set[unit]) {
cifdefaultroute(unit, ouraddr, hisaddr);
default_route_set[unit] = 0;
}
cifaddr(unit, ouraddr, hisaddr);
}
/*
* ipcp_finished - possibly shut down the lower layers.
*/
static void ipcp_finished(fsm *f)
{
np_finished(f->unit, PPP_IP);
}
#pragma argsused
static int ipcp_printpkt(
u_char *p,
int plen,
void (*printer) __P((void *, char *, ...)),
void *arg
)
{
return 0;
}
/*
* ip_active_pkt - see if this IP packet is worth bringing the link up for.
* We don't bring the link up for IP fragments or for TCP FIN packets
* with no data.
*/
#define IP_HDRLEN 20 /* bytes */
#define IP_OFFMASK 0x1fff
#define IPPROTO_TCP 6
#define TCP_HDRLEN 20
#define TH_FIN 0x01
/*
* We use these macros because the IP header may be at an odd address,
* and some compilers might use word loads to get th_off or ip_hl.
*/
#define net_short(x) (((x)[0] << 8) + (x)[1])
#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF)
#define get_ipoff(x) net_short((unsigned char *)(x) + 6)
#define get_ipproto(x) (((unsigned char *)(x))[9])
#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4)
#define get_tcpflags(x) (((unsigned char *)(x))[13])
static int ip_active_pkt(u_char *pkt, int len)
{
u_char *tcp;
int hlen;
len -= PPP_HDRLEN;
pkt += PPP_HDRLEN;
if (len < IP_HDRLEN)
return 0;
if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
return 0;
if (get_ipproto(pkt) != IPPROTO_TCP)
return 1;
hlen = get_iphl(pkt) * 4;
if (len < hlen + TCP_HDRLEN)
return 0;
tcp = pkt + hlen;
if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
return 0;
return 1;
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -