📄 control.c
字号:
#endif strncpy (ip1, IPADDY (c->lns->localaddr), sizeof (ip1)); strncpy (ip2, IPADDY (c->addr), sizeof (ip2)); po = NULL; po = add_opt (po, "passive"); po = add_opt (po, "-detach"); po = add_opt (po, "%s:%s", c->lns->localaddr ? ip1 : "", ip2); if (c->lns->authself) { if (c->lns->pap_refuse) po = add_opt (po, "refuse-pap"); if (c->lns->chap_refuse) po = add_opt (po, "refuse-chap"); } else { po = add_opt (po, "refuse-pap"); po = add_opt (po, "refuse-chap"); } if (c->lns->authpeer) { po = add_opt (po, "auth"); if (c->lns->pap_require) po = add_opt (po, "require-pap"); if (c->lns->chap_require) po = add_opt (po, "require-chap"); if (c->lns->passwdauth) po = add_opt (po, "login"); } if (c->lns->authname[0]) { po = add_opt (po, "name"); po = add_opt (po, c->lns->authname); } if (c->lns->debug) po = add_opt (po, "debug"); if (c->lns->pppoptfile[0]) { po = add_opt (po, "file"); po = add_opt (po, c->lns->pppoptfile); } start_pppd (c, po); opt_destroy (po); log (LOG_LOG, "%s: Call established with %s, Local: %d, Remote: %d, Serial: %d\n", __FUNCTION__, IPADDY (t->peer.sin_addr), c->ourcid, c->cid, c->serno); break; case OCRP: /* jz: nothing to do for OCRP, waiting for OCCN */ break; case OCCN: /* jz: get OCCN, so the only thing we must do is to start the pppd */ po = NULL; po = add_opt (po, "passive"); po = add_opt (po, "-detach"); po = add_opt (po, "file"); strcat (dummy_buf, c->dial_no); /* jz: use /etc/ppp/dialnumber.options for pppd - kick it if you dont like */ strcat (dummy_buf, ".options"); po = add_opt (po, dummy_buf); if (c->lac) { if (c->lac->defaultroute) po = add_opt (po, "defaultroute"); strncpy (ip1, IPADDY (c->lac->localaddr), sizeof (ip1)); strncpy (ip2, IPADDY (c->lac->remoteaddr), sizeof (ip2)); po = add_opt (po, "%s:%s", c->lac->localaddr ? ip1 : "", c->lac->remoteaddr ? ip2 : ""); if (c->lac->authself) { if (c->lac->pap_refuse) po = add_opt (po, "refuse-pap"); if (c->lac->chap_refuse) po = add_opt (po, "refuse-chap"); } else { po = add_opt (po, "refuse-pap"); po = add_opt (po, "refuse-chap"); } if (c->lac->authpeer) { po = add_opt (po, "auth"); if (c->lac->pap_require) po = add_opt (po, "require-pap"); if (c->lac->chap_require) po = add_opt (po, "require-chap"); } if (c->lac->authname[0]) { po = add_opt (po, "name"); po = add_opt (po, c->lac->authname); } if (c->lac->debug) po = add_opt (po, "debug"); if (c->lac->pppoptfile[0]) { po = add_opt (po, "file"); po = add_opt (po, c->lac->pppoptfile); } }; start_pppd (c, po); log (LOG_LOG, "parameters: Local: %d , Remote: %d , Serial: %d , Pid: %d , Tunnelid: %d , Phoneid: %s\n", c->ourcid, c->cid, c->serno, c->pppd, t->ourtid, c->dial_no); /* jz: just show some information */ opt_destroy (po); if (c->lac) c->lac->rtries = 0; break; case CDN: if (c->qcid < 0) { if (DEBUG) log (LOG_DEBUG, "%s: Peer tried to disconnect without specifying call ID\n", __FUNCTION__); return -EINVAL; } if (c == t->self) { p = t->call_head; while (p && (p->cid != c->qcid)) p = p->next; if (!p) { if (DEBUG) log (LOG_DEBUG, "%s: Unable to determine call to be disconnected.\n", __FUNCTION__); return -EINVAL; } } else p = c; if ((c->qcid != p->cid) && p->cid > 0) { if (DEBUG) log (LOG_DEBUG, "%s: Peer tried to disconnect with invalid CID (%d != %d)\n", __FUNCTION__, c->qcid, c->cid); return -EINVAL; } c->qcid = -1; if (c->result < 0) { if (DEBUG) log (LOG_DEBUG, "%s: Peer tried to disconnect without specifying result code.\n", __FUNCTION__); return -EINVAL; } log (LOG_LOG, "%s: Connection closed to %s, serial %d (%s)\n", __FUNCTION__, IPADDY (t->peer.sin_addr), c->serno, c->errormsg); c->needclose = 0; c->closing = -1; break; case Hello: break; case SLI: break; default: log (LOG_DEBUG, "%s: Don't know how to finish a message of type %d\n", __FUNCTION__, c->msgtype); set_error (c, VENDOR_ERROR, "Unimplemented message %d\n", c->msgtype); } return 0;}inline int check_control (const struct buffer *buf, struct tunnel *t, struct call *c){ /* * Check if this is a valid control * or not. Returns 0 on success */ struct control_hdr *h = (struct control_hdr *) (buf->start); struct buffer *zlb; if (buf->len < sizeof (struct control_hdr)) { if (DEBUG) { log (LOG_DEBUG, "%s: Received too small of packet\n", __FUNCTION__); } return -EINVAL; }#ifdef SANITY if (buf->len != h->length) { if (DEBUG) { log (LOG_DEBUG, "%s: Reported and actual sizes differ (%d != %d)\n", __FUNCTION__, h->length, buf->len); } return -EINVAL; } /* * FIXME: H-bit handling goes here */#ifdef DEBUG_CONTROL log (LOG_DEBUG, "%s: control, cid = %d, Ns = %d, Nr = %d\n", __FUNCTION__, c->cid, h->Ns, h->Nr);#endif if (h->Ns != t->control_rec_seq_num) { if (DEBUG) log (LOG_DEBUG, "%s: Received out of order control packet on tunnel %d (%d != %d)\n", __FUNCTION__, t->tid, h->Ns, t->control_rec_seq_num); if (((h->Ns < t->control_rec_seq_num) && ((t->control_rec_seq_num - h->Ns) < 32768)) || ((h->Ns > t->control_rec_seq_num) && ((t->control_rec_seq_num - h->Ns) > 32768))) { /* * Woopsies, they sent us a message we should have already received * so we should send them a ZLB so they know * for sure that we already have it. */#ifdef DEBUG_ZLB if (DEBUG) log (LOG_DEBUG, "%s: Sending an updated ZLB in reponse\n", __FUNCTION__);#endif zlb = new_outgoing (t); control_zlb (zlb, t, c); udp_xmit (zlb); toss (zlb); } else if (!t->control_rec_seq_num && (t->tid == -1)) { /* We made this tunnel just for this message, so let's destroy it. */ c->needclose = 0; c->closing = -1; } return -EINVAL; } else { t->control_rec_seq_num++; c->cnu = -1; } /* * So we know what the other end has received * so far */ t->cLr = h->Nr; if (t->sanity) { if (!CTBIT (h->ver)) { if (DEBUG) { log (LOG_DEBUG, "%s: Control bit not set\n", __FUNCTION__); } return -EINVAL; } if (!CLBIT (h->ver)) { if (DEBUG) { log (LOG_DEBUG, "%s: Length bit not set\n", __FUNCTION__); } return -EINVAL; } if (!CFBIT (h->ver)) { if (DEBUG) { log (LOG_DEBUG, "%s: Flow bit not set\n", __FUNCTION__); } return -EINVAL; } if (CVER (h->ver) != VER_L2TP) { if (DEBUG) { if (CVER (h->ver) == VER_PPTP) { log (LOG_DEBUG, "%s: PPTP packet received\n", __FUNCTION__); } else if (CVER (h->ver) < VER_L2TP) { log (LOG_DEBUG, "%s: L2F packet received\n", __FUNCTION__); } else { log (LOG_DEBUG, "%s: Unknown version received\n", __FUNCTION__); } } return -EINVAL; } }#endif return 0;}inline int check_payload (struct buffer *buf, struct tunnel *t, struct call *c){ /* * Check if this is a valid payload * or not. Returns 0 on success. */ int ehlen = MIN_PAYLOAD_HDR_LEN; struct payload_hdr *h = (struct payload_hdr *) (buf->start); if (!c) { if (DEBUG) { log (LOG_DEBUG, "%s: Aempted to send payload on tunnel\n", __FUNCTION__); } return -EINVAL; } if (buf->len < MIN_PAYLOAD_HDR_LEN) { /* has to be at least MIN_PAYLOAD_HDR_LEN no matter what. we'll look more later */ if (DEBUG) { log (LOG_DEBUG, "%s:Recieved to small of packet\n", __FUNCTION__); } return -EINVAL; }#ifdef SANITY if (t->sanity) { if (PTBIT (h->ver)) { if (DEBUG) { log (LOG_DEBUG, "%s Control bit set\n", __FUNCTION__); } return -EINVAL; } if (PLBIT (h->ver)) ehlen += 2; /* Should have length information */ if (PFBIT (h->ver)) {/* if (!c->fbit && !c->ourfbit) { if (DEBUG) log(LOG_DEBUG,"%s: flow bit set, but no RWS negotiated.\n",__FUNCTION__); return -EINVAL; } */ ehlen += 4; /* Should have Ns and Nr too */ }/* if (!PFBIT(h->ver)) { if (c->fbit || c->ourfbit) { if (DEBUG) log(LOG_DEBUG, "%s: no flow bit, but RWS was negotiated.\n",__FUNCTION__); return -EINVAL;; } } */ if (PSBIT (h->ver)) ehlen += 4; /* Offset information */ if (PLBIT (h->ver)) ehlen += h->length; /* include length if available */ if (PVER (h->ver) != VER_L2TP) { if (DEBUG) { if (PVER (h->ver) == VER_PPTP) { log (LOG_DEBUG, "%s: PPTP packet received\n", __FUNCTION__); } else if (CVER (h->ver) < VER_L2TP) { log (LOG_DEBUG, "%s: L2F packet received\n", __FUNCTION__); } else { log (LOG_DEBUG, "%s: Unknown version received\n", __FUNCTION__); } } return -EINVAL; } if ((buf->len < ehlen) && !PLBIT (h->ver)) { if (DEBUG) { log (LOG_DEBUG, "%s payload too small (%d < %d)\n", __FUNCTION__, buf->len, ehlen); } return -EINVAL; } if ((buf->len != h->length) && PLBIT (h->ver)) { if (DEBUG) { log (LOG_DEBUG, "%s: size mismatch (%d != %d)\n", __FUNCTION__, buf->len, h->length); } return -EINVAL; } }#endif return 0;}inline int expand_payload (struct buffer *buf, struct tunnel *t, struct call *c){ /* * Expands payload header. Does not check for valid header, * check_payload() should already be called as a prerequisite. */ struct payload_hdr *h = (struct payload_hdr *) (buf->start); _u16 *r = (_u16 *) h; /* Nice to have raw word pointers */ struct payload_hdr *new_hdr; int ehlen = 0; /* * We first calculate our offset */ if (!PLBIT (h->ver)) ehlen += 2; /* Should have length information */ if (!PFBIT (h->ver)) ehlen += 4; /* Should have Ns and Nr too */ if (!PSBIT (h->ver)) ehlen += 4; /* Offset information */ if (ehlen) { /* * If this payload is missing any information, we'll * fill it in */ new_hdr = (struct payload_hdr *) (buf->start - ehlen); if ((void *) new_hdr < (void *) buf->rstart) { log (LOG_WARN, "%s: not enough space to decompress frame\n", __FUNCTION__); return -EINVAL; }; new_hdr->ver = *r; if (PLBIT (new_hdr->ver)) { r++; new_hdr->length = *r; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -